home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / video / bxutil-c.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  80KB  |  3,167 lines

  1. /*
  2.  * Copyright (C) 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  * MODULE: BxConvert.c
  19.  * AUTHOR: Automatically generated by Builder Xcessory
  20.  * 
  21.  * Description: This module contains various utilities, converters 
  22.  *    for XmStrings (to work properly with app-defaults), and if needed
  23.  *    the XPM pixmap utilities.
  24.  *    
  25.  * Edit the file ${BX}/gen/bxutils.c (BX$SYSTEM:[gen]bxutils.c) to make
  26.  * system wide changes to this file which will be visible next time
  27.  * this file is generated. 
  28.  * ${BX} is the directory where Builder Xcessory is installed.
  29.  */
  30. /*
  31.  * The string version of a Bx generated compound string is :
  32.  *
  33.  *        ::[#tag][:t][:r]["str"]
  34.  *
  35.  * where:
  36.  *    :: = indicates compound string.
  37.  *    tag =  the font tag
  38.  *    :t = separator (if not seen no separator added to segment)
  39.  *    :r = right to left (if not seen left to right assumed)
  40.  *    "str" = the text of the string.
  41.  *
  42.  * The components for the compound string can be repeated any number of
  43.  * times.
  44.  */
  45.  
  46. /*****************************************************************************
  47.  *       INCLUDE FILES
  48.  *****************************************************************************/
  49.  
  50. #include <Xm/Xm.h>
  51. #include <Xm/RowColumn.h>
  52. #include <stdio.h>
  53. #include <ctype.h>
  54.  
  55. /*
  56.  * Include stdlib.h and malloc.h if code is C++, ANSI, or Extended ANSI.
  57.  */
  58. #if defined(__cplusplus) || defined(__STDC__) || defined(__EXTENSIONS__)
  59. #include <stdlib.h>
  60. #include <malloc.h>
  61. #endif
  62.  
  63. /*****************************************************************************
  64.  *       TYPDEFS AND DEFINES
  65.  *****************************************************************************/
  66.  
  67. #ifdef _NO_PROTO
  68. #ifdef NeedFunctionPrototypes
  69. #undef NeedFunctionPrototypes
  70. #endif
  71. #endif
  72.  
  73. /*
  74.  * Define SUPPORTS_WCHARS if the system supports wide character sets
  75.  */
  76. #ifdef VMS
  77. typedef    char    wchar_t;
  78. #else
  79. #define SUPPORTS_WCHARS
  80. #endif
  81.  
  82. #define UNSET (-1)
  83.  
  84. #define NEW_LINE    '\012'
  85.  
  86. /*
  87.  * Set state of inclusion of prototypes properly
  88.  */
  89. #ifdef NeedFunctionPrototypes
  90. #define ARGLIST(p)    (
  91. #define ARG(a, b)    a b,
  92. #define GRA(a, b)    a b)
  93. #else
  94. #define ARGLIST(p)    p
  95. #define ARG(a, b)    a b;
  96. #define GRA(a, b)    a b;
  97. #endif
  98.  
  99. #ifdef VMS
  100. #define STRCASECMP    StrCasecmp
  101. #else
  102. #define STRCASECMP    strcasecmp
  103. #endif
  104.  
  105. #ifdef __cplusplus
  106. #define XTPOINTER    XPointer
  107. #else
  108. #define XTPOINTER    XtPointer
  109. #endif
  110.  
  111. /*****************************************************************************
  112.  *       GLOBAL DECLARATIONS
  113.  *****************************************************************************/
  114.  
  115. /*****************************************************************************
  116.  *       EXTERNAL DECLARATIONS
  117.  *****************************************************************************/
  118.  
  119. /*****************************************************************************
  120.  *    STATIC DECLARATION
  121.  *****************************************************************************/
  122.  
  123. static wchar_t*    emptyStrWcs = {0};
  124.  
  125. #ifndef NeedFunctionPrototypes
  126. #ifndef SUPPORTS_WCHARS
  127. static int     mblen            ();
  128. #endif
  129.  
  130. static int    strlenWc        ();
  131. static size_t    doMbstowcs        ();
  132. static size_t    doWcstombs         ();
  133. static void    copyWcsToMbs        ();
  134. static Boolean    extractSegment        ();
  135. static XmString    StringToXmString    ();
  136. static char*    getNextCStrDelim    ();
  137. static int    getCStrCount        ();
  138.  
  139. #else
  140. #ifndef SUPPORTS_WCHARS
  141. static int     mblen            (char*, size_t);
  142. #endif
  143.  
  144. static int    strlenWc        (wchar_t*);
  145. static size_t    doMbstowcs        (wchar_t*, char*, size_t);
  146. static size_t    doWcstombs         (char*, wchar_t*, size_t);
  147. static void    copyWcsToMbs        (char*, wchar_t*, int);
  148. static Boolean    extractSegment        (wchar_t**, wchar_t**, int *,
  149.                      wchar_t**, int*, int*,    Boolean*);
  150. static XmString    StringToXmString    (char*);
  151. static char*    getNextCStrDelim    (char*);
  152. static int    getCStrCount        (char*);
  153.  
  154. #endif
  155.  
  156. /*****************************************************************************
  157.  *    STATIC CODE
  158.  *****************************************************************************/
  159.  
  160. #ifdef VMS
  161. static int StrCasecmp
  162. ARGLIST((s1, s2))
  163. ARG(register char *, s1)
  164. GRA(register char *, s2)
  165. {
  166.     register int        c1, c2;
  167.     
  168.     while (*s1 && *s2)
  169.     {
  170.         c1 = isupper(*s1) ? tolower(*s1) : *s1;
  171.         c2 = isupper(*s2) ? tolower(*s2) : *s2;
  172.         if (c1 != c2)
  173.         {
  174.             return (1);
  175.         }
  176.         s1++;
  177.         s2++;
  178.     }
  179.     if (*s1 || *s2)
  180.     {
  181.         return (1);
  182.     }
  183.     return (0);
  184. }
  185. #endif
  186.  
  187. #ifndef SUPPORTS_WCHARS
  188. static int mblen
  189. ARGLIST((s, n))
  190. ARG(char *, s)
  191. GRA(size_t, n)
  192. {
  193.     return 1;
  194. }
  195. #endif
  196.  
  197.  
  198. /*
  199.  * Function:
  200.  *      strlenWc()
  201.  * Description:
  202.  *      Return the number of characters in a wide character string (not
  203.  *    the characters in the resultant mbs).
  204.  * Input:
  205.  *      ptr - wchar_t* : pointer to the wcs to count
  206.  * Output:
  207.  *      int : the number of characters found
  208.  */
  209. static int strlenWc
  210. ARGLIST((ptr))
  211. GRA(wchar_t *,ptr)
  212. {
  213.     register wchar_t    *p = ptr;
  214.     register int    x = 0;
  215.  
  216.     if (!ptr) return(0);
  217.  
  218.     while(*p++)    x++;
  219.     return(x);
  220. }
  221.  
  222. /*
  223.  * Function:
  224.  *      doMbstowcs()
  225.  * Description:
  226.  *      Create a wcs string from an input mbs. 
  227.  * Input:
  228.  *    wcs - wchar_t* : pointer to result buffer of wcs
  229.  *      mbs - char* : pointer to the source mbs
  230.  *    n - size_t : the number of characters to convert
  231.  * Output:
  232.  *      size_t : number of bytes converted
  233.  */
  234. static size_t doMbstowcs
  235. ARGLIST((wcs, mbs, n))
  236. ARG(wchar_t *,wcs)
  237. ARG(char *, mbs)
  238. GRA(size_t, n)
  239. {
  240. #ifndef SUPPORTS_WCHARS
  241.     strncpy((char*)wcs, mbs, n);
  242.     return(n);
  243. #else
  244.     return(mbstowcs(wcs, mbs, n));
  245. #endif
  246. }
  247.  
  248. /*
  249.  * Function:
  250.  *      doWcstombs()
  251.  * Description:
  252.  *      Create a mbs string from an input wcs.
  253.  * Input:
  254.  *    wcs - wchar_t* : pointer to the source wcs
  255.  *      mbs - char* : pointer to result mbs buffer 
  256.  *    n - size_t : the number of characters to convert
  257.  * Output:
  258.  *      size_t : number of bytes converted
  259.  */
  260. static size_t doWcstombs
  261. ARGLIST((mbs, wcs, n))
  262. ARG(char *, mbs)
  263. ARG(wchar_t *, wcs)
  264. GRA(size_t, n)
  265. {
  266. #ifndef SUPPORTS_WCHARS
  267.     strncpy(mbs, (char*)wcs, n);
  268.     return(n);
  269. #else
  270.     return(wcstombs(mbs, wcs, n));
  271. #endif
  272. }
  273.  
  274. /*
  275.  * Function:
  276.  *      copyWcsToMbs(mbs, wcs, len);
  277.  * Description:
  278.  *      Create a mbs string from an input wcs. This function allocates
  279.  *    a buffer if necessary.
  280.  * Input:
  281.  *    mbs - char* : destination for the converted/copied output
  282.  *    wcs - wchar_t* : pointer to wcs to copy/convert
  283.  *    len - int : the number of wchar_t' to convert
  284.  * Output:
  285.  *      None
  286.  */
  287. static void copyWcsToMbs
  288. ARGLIST((mbs, wcs, len))
  289. ARG(char *, mbs)
  290. ARG(wchar_t *, wcs)
  291. GRA(int, len)
  292. {
  293. #ifdef SUPPORTS_WCHARS
  294.     static    wchar_t    *tbuf;
  295.     static    int    tbufSize = 0;
  296.     int        numCvt;
  297.  
  298.     /*
  299.      * Make sure there's room in the buffer
  300.      */
  301.     if (tbufSize == 0)
  302.     {
  303.     tbuf = (wchar_t*)malloc((len + 1) * sizeof(wchar_t));
  304.     tbufSize = len;
  305.     }
  306.     else if (tbufSize < len)
  307.     {
  308.     tbuf = (wchar_t*)realloc((char*)tbuf, (len + 1) * sizeof(wchar_t));
  309.     tbufSize = len;
  310.     }
  311.  
  312.     memcpy((char*)tbuf, (char*)wcs, len * sizeof(wchar_t));
  313.     numCvt = wcstombs(mbs, wcs, len);
  314.     mbs[numCvt] = '\0';
  315. #else
  316.     memcpy(mbs, (char*)wcs, len);
  317.     mbs[len] = '\0';
  318. #endif
  319. }    
  320.  
  321. /*
  322.  * Function:
  323.  *    ptr = getNextSepartor(str);
  324.  * Description:
  325.  *    Parse through a string looking for the next compound string
  326.  *    field separator
  327.  * Inputs:
  328.  *    str - wchar_t* : the address of address of the string to parse
  329.  * Outputs:
  330.  *    ptr - wchar_t* : pointer to character, if found, points to end
  331.  *            of string otherwise ('\0').
  332.  */
  333. static wchar_t* getNextSeparator
  334. ARGLIST((str))
  335. GRA(wchar_t *, str)    
  336. {
  337.     wchar_t    *ptr = str;
  338.     
  339.     while (*ptr)
  340.     {
  341.     /*
  342.      * Check for separator
  343.      */
  344.     switch (*ptr)
  345.     {
  346.     case '#':
  347.         return(ptr);
  348.     case '\"':
  349.         return(ptr);
  350.     case ':':
  351.         return(ptr);
  352.     case '\\':
  353.         ptr++;
  354.         if (*ptr) ptr++;    /* Skip quoted character */
  355.         break;
  356.     default:
  357.         ptr++;
  358.         break;
  359.     }
  360.     }
  361.     return(ptr);
  362. }
  363.  
  364. /*
  365.  * Function:
  366.  *    more =
  367.  *        extractSegment(str, tagStart, tagLen, txtStart, txtLen, 
  368.  *            pDir, pSep);
  369.  * Description:
  370.  *    Parse through a string and find it's segment, seperator
  371.  *    direction and font tag.
  372.  * Inputs:
  373.  *    str - char** : the address of address of the string to parse
  374.  *    tagStart - char** : address to return pointer to tag start into 
  375.  *    tagLen - int* : address where to return the tag length into
  376.  *    txtStart - char** : address to return the text start into
  377.  *    txtLen - int* : address where to return the text length
  378.  *    pDir - int* : address to return the string direction into
  379.  *    pSep - Boolean * : address to return the separtor into
  380.  * Outputs:
  381.  *    more - Boolean : True if more of the string to parse.
  382.  *            False means done.
  383.  */
  384. static Boolean extractSegment
  385. ARGLIST((str, tagStart, tagLen, txtStart, txtLen, pDir, pSep))
  386. ARG(wchar_t **, str)
  387. ARG(wchar_t **, tagStart)
  388. ARG(int *, tagLen)
  389. ARG(wchar_t **, txtStart)
  390. ARG(int *, txtLen)
  391. ARG(int *, pDir)
  392. GRA(Boolean *, pSep)
  393. {
  394.     wchar_t        *start;
  395.     wchar_t        *text;
  396.     int            textL;
  397.     Boolean        tagSeen;
  398.     wchar_t        *tag;
  399.     int            tagL;
  400.     Boolean        modsSeen;
  401.     Boolean        sep;
  402.     int            dir;
  403.     Boolean        done;
  404.     int            *lenUp;
  405.     Boolean        checkDir;
  406.  
  407.     /*
  408.      * Initialize variables
  409.      */
  410.     text = NULL;
  411.     textL = 0;
  412.     tagSeen = False;
  413.     tag = NULL;
  414.     tagL = 0;
  415.     modsSeen = False;
  416.     dir = XmSTRING_DIRECTION_L_TO_R;
  417.     sep = False;
  418.     done = False;
  419.     lenUp = NULL;
  420.  
  421.     /*
  422.      * Guard against nulls
  423.      */
  424.     if (!(start = *str))
  425.     {
  426.     start = emptyStrWcs;
  427.     }
  428.  
  429.     /*
  430.      * If the first character of the string isn't a # or a ", then we
  431.      * just have a regular old simple string. Do the same the thing for
  432.      * the empty string.
  433.      */
  434.     if ((*start == '\0') || (start != getNextSeparator(start)))
  435.     {
  436.     text = start;
  437.     if (!(textL = strlenWc(start)))
  438.     {
  439.         text = NULL;
  440.     }
  441.     start += textL;
  442.     }
  443.     else
  444.     {
  445.     done = False;
  446.     while (!done)
  447.     {
  448.         switch (*start)
  449.         {
  450.         case '#':
  451.         if (tagSeen)
  452.         {
  453.             done = True;
  454.             break;
  455.         }
  456.         
  457.         tagSeen = True;
  458.         tag = ++start;
  459.         start = getNextSeparator(tag);
  460.         if ((tagL = start - tag) == 0)
  461.         {
  462.             tag = NULL;        /* Null tag specified */
  463.         }
  464.         break;
  465.  
  466.         case '\"':
  467.         text = ++start;
  468.         start = getNextSeparator(start);
  469.         while (!((*start == '\"') || (*start == '\0')))
  470.         {
  471.             start = getNextSeparator(++start);
  472.         }
  473.          
  474.         if ((textL = start - text) == 0)
  475.         {
  476.             text = NULL;    /* Null text specified  */
  477.         }
  478.         if (*start == '\"')    /* if a quote, skip over it */
  479.         {
  480.             start++;
  481.         }
  482.         done = True;
  483.         break;
  484.         
  485.         case ':':
  486.         if (modsSeen)
  487.         {
  488.             done = True;
  489.             break;
  490.         }
  491.  
  492.         /*
  493.          * If the next character is a t or f, the we've got 
  494.          * a separator.
  495.          */
  496.         modsSeen = True;
  497.         checkDir = False;
  498.         start++;
  499.         if ((*start == 't') || (*start == 'T') || (*start == '1'))
  500.         {
  501.             sep = True;
  502.             start++;
  503.             checkDir = True;
  504.         }
  505.         else if ((*start == 'f') || (*start == 'F') || (*start == '0'))
  506.         {
  507.             sep = False;
  508.             start++;
  509.             checkDir = True;
  510.         }
  511.         else if ((*start == 'r') || (*start == 'R'))
  512.         {
  513.             start++;
  514.             dir = XmSTRING_DIRECTION_R_TO_L;
  515.         }
  516.         else if ((*start == 'l') || (*start == 'L'))
  517.         {
  518.             start++;
  519.             dir = XmSTRING_DIRECTION_L_TO_R;
  520.         }
  521.  
  522.         /*
  523.          * Look for direction if necessary. This requires a bit of
  524.          * look ahead.
  525.          */
  526.         if (checkDir && (*start == ':'))
  527.         {
  528.             if ((*(start + 1) == 'l') || (*(start + 1) == 'L'))
  529.             {
  530.             dir = XmSTRING_DIRECTION_L_TO_R;
  531.             start += 2;
  532.             }
  533.             else if ((*(start + 1) == 'r') || (*(start + 1) == 'R'))
  534.             {
  535.             dir = XmSTRING_DIRECTION_R_TO_L;
  536.             start+=2;
  537.             }
  538.         }
  539.         break;
  540.  
  541.         default:
  542.         /*
  543.          * HACK HACK HACK HACK
  544.          * Error... just skip character for now
  545.          */
  546.         start++;
  547.         break;
  548.         }
  549.     }
  550.     }
  551.  
  552.     /*
  553.      * Now fill in return values
  554.      */
  555.     if (*str)        *str = start;
  556.     if (tagStart)    *tagStart = tag;
  557.     if (tagLen)        *tagLen = tagL;
  558.     if (txtStart)    *txtStart = text;
  559.     if (txtLen)        *txtLen = textL;
  560.     if (pDir)        *pDir = dir;
  561.     if (pSep)        *pSep = sep;
  562.  
  563.     return ((*start == '\0') ? False : True);
  564. }
  565.  
  566. /*
  567.  * Function:
  568.  *    xstr = StringToXmString(str);
  569.  * Description:
  570.  *    Parse a string into an XmString.
  571.  * Inputs:
  572.  *    str - char * : the string to parse
  573.  *
  574.  * Outputs:
  575.  *    xstr - XmString : the allocated return structure
  576.  */
  577. static XmString StringToXmString
  578. ARGLIST((str))
  579. GRA(char *,str)
  580. {
  581.     static char*    tagBuf;
  582.     static int        tagBufLen;
  583.     static char*    textBuf;
  584.     static int        textBufLen;
  585.  
  586.     wchar_t        *ctx;
  587.     wchar_t        *tag;
  588.     int            tagLen;
  589.     wchar_t        *text;
  590.     int            textLen;
  591.     Boolean        sep;
  592.     int            dir;
  593.     
  594.     Boolean        more;
  595.     wchar_t        *wcStr;
  596.     int            curDir;
  597.     XmString        xmStr;
  598.     XmString        s1;
  599.     XmString        s2;
  600.  
  601.     if (!str) return(NULL);
  602.  
  603.     /*
  604.      * For expediencies sake, we'll overallocate this buffer so that
  605.      * the wcs is guaranteed to fit (1 wc per byte in original string).
  606.      */
  607.     wcStr = (wchar_t*)malloc((strlen(str) + 1) * sizeof(wchar_t));
  608.     doMbstowcs(wcStr, str, strlen(str) + 1);
  609.  
  610.     /*
  611.      * Create the beginning segment
  612.      */
  613.     curDir = XmSTRING_DIRECTION_L_TO_R;
  614.     xmStr = XmStringDirectionCreate(curDir);
  615.  
  616.     /*
  617.      * Scan the string and get the overall text length
  618.      */
  619.     more = True;
  620.     ctx = wcStr;
  621.     while (more)
  622.     {
  623.     more = extractSegment(&ctx, &tag, &tagLen,
  624.                   &text, &textLen, &dir, &sep);
  625.     /*
  626.      * Pick up a direction change
  627.      */
  628.     if (dir != curDir)
  629.     {
  630.         curDir = dir;
  631.         s1 = XmStringDirectionCreate(curDir);
  632.         s2 = xmStr;
  633.         xmStr = XmStringConcat(s2, s1);
  634.         XmStringFree(s1);
  635.         XmStringFree(s2);
  636.     }
  637.  
  638.     /*
  639.      * Create the segment.
  640.      */
  641.     if (textLen)
  642.     {
  643.         if (textBufLen <= (textLen * sizeof(wchar_t)))
  644.         {
  645.         textBufLen = (textLen + 1) * sizeof(wchar_t);
  646.         if (textBuf)
  647.         {
  648.             textBuf = (char*)realloc(textBuf, textBufLen);
  649.         }
  650.         else
  651.         {
  652.             textBuf = (char*)malloc(textBufLen);
  653.         }
  654.         }
  655.  
  656.         copyWcsToMbs(textBuf, text, textLen);
  657.  
  658.         if (tagLen)
  659.         {
  660.         if (tagBufLen <= (tagLen * sizeof(wchar_t)))
  661.         {
  662.             tagBufLen = (tagLen + 1) * sizeof(wchar_t);
  663.             if (tagBuf)
  664.             {
  665.             tagBuf = (char*)realloc(tagBuf, tagBufLen);
  666.             }
  667.             else
  668.             {
  669.             tagBuf = (char*)malloc(tagBufLen);
  670.             }
  671.         }
  672.         copyWcsToMbs(tagBuf, tag, tagLen);
  673.         }
  674.         else
  675.         {
  676.         if (!tagBuf)
  677.         {
  678.             tagBufLen = strlen(XmSTRING_DEFAULT_CHARSET) + 1;
  679.             tagBuf = (char*)malloc(tagBufLen);
  680.         }
  681.         strcpy(tagBuf, XmSTRING_DEFAULT_CHARSET);
  682.         }
  683.  
  684.         s1 = XmStringCreate(textBuf, tagBuf); 
  685.         s2 = xmStr;
  686.         xmStr = XmStringConcat(s2, s1);
  687.         XmStringFree(s1);
  688.         XmStringFree(s2);
  689.     }
  690.  
  691.     if (sep)
  692.     {
  693.         s1 = XmStringSeparatorCreate();
  694.         s2 = xmStr;
  695.         xmStr = XmStringConcat(s2, s1);
  696.         XmStringFree(s1);
  697.         XmStringFree(s2);
  698.     }
  699.     }
  700.     
  701.     /*
  702.      * Free up memory and return
  703.      */
  704.     free((char*)wcStr);
  705.     return(xmStr);
  706. }
  707. /*
  708.  * Function:
  709.  *      nextCStr = getNextCStrDelim(str)
  710.  * Description:
  711.  *      Find the next unquoted , or \n in the string
  712.  * Input:
  713.  *    str - char * : the input string
  714.  * Output:
  715.  *      nextCStr - char* : pointer to the next delimiter. Returns NULL if no
  716.  *            delimiter found.
  717.  */
  718. static char* getNextCStrDelim
  719. ARGLIST((str))
  720. GRA(char *,str)
  721. {
  722.     char    *comma = str;
  723.     Boolean    inQuotes = False;
  724.     int        len;
  725.  
  726.     if (!str) return(NULL);
  727.     if (!*str) return(NULL);    /* At end */
  728.  
  729.     mblen(NULL, sizeof(wchar_t));
  730.     while (*comma)
  731.     {
  732.     if ((len = mblen(comma, sizeof(wchar_t))) > 1)
  733.     {
  734.         comma += len;
  735.         continue;
  736.     }
  737.     
  738.     if (*comma == '\\')
  739.     {
  740.         comma++;    /* Over quote */
  741.         comma += mblen(comma, sizeof(wchar_t));
  742.         continue;
  743.     }
  744.  
  745.     /*
  746.      * See if we have a delimiter
  747.      */
  748.     if (!inQuotes)
  749.     {
  750.         if ((*comma == ',') || (*comma == '\012'))
  751.         {
  752.         return(comma);
  753.         }
  754.     }
  755.  
  756.     /*
  757.      * Deal with quotes
  758.      */
  759.     if (*comma == '\"')
  760.     {
  761.         inQuotes = ~inQuotes;
  762.     }
  763.  
  764.     comma++;
  765.     }
  766.  
  767.     return(NULL);        /* None found */
  768. }
  769.  
  770. /*
  771.  * Function:
  772.  *    cnt = getCStrCount(str);
  773.  * Description:
  774.  *      Get the count of cstrings in a compound string table ascii
  775.  *    format.
  776.  * Input:
  777.  *      str - char * : string to parse
  778.  * Output:
  779.  *      cnt - int : the number of XmStrings found
  780.  */
  781. static int getCStrCount
  782. ARGLIST((str))
  783. GRA(char *, str)
  784. {
  785.     int        x = 1;
  786.     char    *newStr;
  787.  
  788.     if (!str) return(0);
  789.     if (!*str) return(0);
  790.  
  791.     while (newStr = getNextCStrDelim(str))
  792.     {
  793.     x++;
  794.     str = ++newStr;
  795.     }
  796.     return(x);
  797. }
  798.  
  799. /*
  800.  * Function:
  801.  *    CONVERTER CvtStringToXmString
  802.  *
  803.  * Description:
  804.  *    Convert a string to an XmString. This allows a string contained in
  805.  *    resource file to contain multiple fonts. The syntax for the string
  806.  *    is:
  807.  *        ::[#[font-tag]]"string"[#[font-tag]"string"] ...
  808.  *
  809.  *    note that the # can be escaped (\#).
  810.  *
  811.  * Input:
  812.  * Output:
  813.  *    Standard.
  814.  */
  815. static Boolean CvtStringToXmString
  816. ARGLIST((d, args, num_args, fromVal, toVal, data))
  817. ARG(Display *, d)
  818. ARG(XrmValue *, args)
  819. ARG(Cardinal *, num_args)
  820. ARG(XrmValue *, fromVal)
  821. ARG(XrmValue *, toVal)
  822. GRA(XtPointer, data)
  823. {
  824.     static XmString    resStr;
  825.     char        *str;
  826.  
  827.     /*
  828.      * This converter takes no parameters
  829.      */
  830.     if (*num_args != 0)
  831.     {
  832.     XtAppWarningMsg(XtDisplayToApplicationContext(d), 
  833.             "cvtStringToXmString", "wrongParameters",
  834.             "XtToolkitError",
  835.               "String to XmString converter needs no extra arguments",
  836.             (String *)NULL, (Cardinal *)NULL);
  837.     }
  838.  
  839.     /*
  840.      * See if this is a simple string
  841.      */
  842.     str = (char*)fromVal->addr;
  843.     if (strncmp(str, "::", 2))
  844.     {
  845.     resStr = XmStringCreateLtoR(fromVal->addr, XmSTRING_DEFAULT_CHARSET);
  846.     }
  847.     else
  848.     {
  849.     /*
  850.      * Convert into internal format
  851.      */
  852.     resStr = StringToXmString(fromVal->addr + 2);    /* skip :: */
  853.     }
  854.  
  855.     /*
  856.      * Done, return result
  857.      */
  858.     if (toVal->addr == NULL)
  859.     {
  860.     toVal->addr = (XTPOINTER)&resStr;
  861.     toVal->size = sizeof(XmString);
  862.     }
  863.     else if (toVal->size < sizeof(XmString))
  864.     {
  865.     toVal->size = sizeof(XmString);
  866.     XtDisplayStringConversionWarning(d, fromVal->addr, "XmString");
  867.     XmStringFree(resStr);
  868.     return(False);
  869.     }
  870.     else 
  871.     {
  872.     *(XmString *)toVal->addr = resStr;
  873.     toVal->size = sizeof(XmString);
  874.     }
  875.     return(True);
  876. }
  877.  
  878. static void XmStringCvtDestroy
  879. ARGLIST((app, to, data, args, num_args))
  880. ARG(XtAppContext, app)
  881. ARG(XrmValue *, to)
  882. ARG(XtPointer, data)
  883. ARG(XrmValue *, args)
  884. GRA(Cardinal *, num_args)
  885. {
  886.     XmStringFree(*(XmString*)(to->addr));
  887. }
  888.  
  889. /*
  890.  * Function:
  891.  *    CONVERTER CvtStringToXmStringTable
  892.  *
  893.  * Description:
  894.  *    Convert a string to an XmString table. This allows a string contained in
  895.  *    resource file to contain multiple fonts. The syntax for the string
  896.  *    is:
  897.  *       compound_string = [#[font-tag]]"string"[#[font-tag]"string"] ...
  898.  *       compound_string_table = [compound_string][,compound_string] ...
  899.  *
  900.  *    note that the # can be escaped (\#).
  901.  *
  902.  * Input:
  903.  * Output:
  904.  *    Standard.
  905.  */
  906. static Boolean CvtStringToXmStringTable
  907. ARGLIST((d, args, num_args, fromVal, toVal, data))
  908. ARG(Display *, d)
  909. ARG(XrmValue *, args)
  910. ARG(Cardinal *, num_args)
  911. ARG(XrmValue *, fromVal)
  912. ARG(XrmValue *, toVal)
  913. GRA(XtPointer, data)
  914. {
  915.     static XmString    *CStrTable;
  916.     XmString        *tblPtr;
  917.     char        *str;
  918.     char        *tmpBuf;
  919.     char        *nextDelim;
  920.     XrmValue        fVal;
  921.     XrmValue        tVal;
  922.  
  923.     /*
  924.      * This converter takes no parameters
  925.      */
  926.     if (*num_args != 0)
  927.     {
  928.     XtAppWarningMsg(XtDisplayToApplicationContext(d), 
  929.             "cvtStringToXmStringTable", "wrongParameters",
  930.             "XtToolkitError",
  931.             "String to XmStringTable converter needs no extra arguments",
  932.             (String *)NULL, (Cardinal *)NULL);
  933.     }
  934.  
  935.     /*
  936.      * Set str and make sure there's somethin' there
  937.      */
  938.     if (!(str = (char*)fromVal->addr))
  939.     {
  940.     str = "";
  941.     }
  942.  
  943.     /*
  944.      * Allocate the XmStrings + 1 for NULL termination
  945.      */
  946.     CStrTable = (XmString*)malloc((getCStrCount(str) + 1) * sizeof(XmString*));
  947.  
  948.     /*
  949.      * Use the string converter for the strings
  950.      */
  951.     tmpBuf = (char*)malloc(strlen(str) + 1);
  952.     strcpy(tmpBuf, str);
  953.     str = tmpBuf;
  954.  
  955.     /*
  956.      * Create strings
  957.      */
  958.     tblPtr = CStrTable;
  959.     if (*str)
  960.     {
  961.     while (str)
  962.     {
  963.         nextDelim = getNextCStrDelim(str);
  964.         
  965.         /*
  966.          * Overwrite nextDelim
  967.          */
  968.         if (nextDelim)
  969.         {
  970.         *nextDelim = '\0';
  971.         nextDelim++;
  972.         }
  973.         
  974.         /*
  975.          * Convert it
  976.          */
  977.         fVal.size = strlen(str) + 1;
  978.         fVal.addr = str;
  979.         tVal.size = sizeof(XTPOINTER);
  980.         tVal.addr = (XTPOINTER)tblPtr;
  981.         
  982.         /*
  983.          * Call converter ourselves since this is used to create
  984.          * the strings in the table we create. We need to do this
  985.          * since we don't have a widget to send to the XtConvertAndStore
  986.          * function. Side effects are that we can never get these
  987.          * compound strings cached and that no destructor function is
  988.          * called when the strings leave existance, but we nuke 'em
  989.          * in the XmStringTable destuctor.
  990.          */
  991.         CvtStringToXmString(d, args, num_args, &fVal, &tVal, NULL);
  992.         tblPtr++;
  993.         str = nextDelim;
  994.     }
  995.     }
  996.     free(tmpBuf);
  997.  
  998.     /*
  999.      * Null terminate
  1000.      */
  1001.     *tblPtr = NULL;
  1002.  
  1003.     /*
  1004.      * Done, return result
  1005.      */
  1006.     if (toVal->addr == NULL)
  1007.     {
  1008.     toVal->addr = (XTPOINTER)&CStrTable;
  1009.     toVal->size = sizeof(XmString);
  1010.     }
  1011.     else if (toVal->size < sizeof(XmString*))
  1012.     {
  1013.     toVal->size = sizeof(XmString*);
  1014.     XtDisplayStringConversionWarning(d, fromVal->addr, "XmStringTable");
  1015.  
  1016.     tblPtr = CStrTable;
  1017.     while (*tblPtr)
  1018.     {
  1019.         XmStringFree(*tblPtr);
  1020.     }
  1021.     free((char*)CStrTable);
  1022.     return(False);
  1023.     }
  1024.     else 
  1025.     {
  1026.     *(XmString **)toVal->addr = CStrTable;
  1027.     toVal->size = sizeof(XmString*);
  1028.     }
  1029.     return(True);
  1030. }
  1031.  
  1032. static void XmStringTableCvtDestroy
  1033. ARGLIST((app, to, data, args, num_args))
  1034. ARG(XtAppContext, app)
  1035. ARG(XrmValue *, to)
  1036. ARG(XtPointer, data)
  1037. ARG(XrmValue *, args)
  1038. GRA(Cardinal *, num_args)
  1039. {
  1040.     XmString    *tblPtr = *(XmString**)(to->addr);
  1041.  
  1042.     while (*tblPtr)
  1043.     {
  1044.     XmStringFree(*tblPtr);
  1045.     }
  1046.     free((char*)(*(XmString**)(to->addr)));
  1047. }    
  1048.  
  1049. /*****************************************************************************
  1050.  *    GLOBAL CODE
  1051.  *****************************************************************************/
  1052.  
  1053. /*
  1054.  * Function:
  1055.  *      RegisterBxConverters(appContext);
  1056.  * Description:
  1057.  *      This globally available function installs all the converters necessary
  1058.  *    to run BuilderXcessory generated interfaces that use compound
  1059.  *    strings. This is necessary since Motif has not supplied very smart
  1060.  *    converters.
  1061.  * Input:
  1062.  *      appContext - XtAppContext : the application context
  1063.  * Output:
  1064.  *      None
  1065.  */
  1066. void RegisterBxConverters
  1067. ARGLIST((appContext))
  1068. GRA(XtAppContext, appContext)
  1069. {
  1070.     XtAppSetTypeConverter(appContext, XmRString, XmRXmString,
  1071.               (XtTypeConverter)CvtStringToXmString,
  1072.               NULL, 0, XtCacheNone, XmStringCvtDestroy);
  1073.  
  1074.     XtAppSetTypeConverter(appContext, XmRString, XmRXmStringTable,
  1075.               (XtTypeConverter)CvtStringToXmStringTable,
  1076.               NULL, 0, XtCacheNone, XmStringTableCvtDestroy);
  1077. }
  1078.  
  1079. /*
  1080.  * Function:
  1081.  *      CONVERT(w, from_string, to_type, to_size, success);
  1082.  * Description:
  1083.  *      A converter wrapper for convenience from BuilderXcessory.
  1084.  * Input:
  1085.  *      w - Widget : the widget to use for conversion
  1086.  *    from_string - char * : the string to convert from
  1087.  *    to_type - char * : the type to convert to
  1088.  *    to_size - int : the size of the conversion result
  1089.  *    success - Boolean* : Set to the result value of the conversion
  1090.  * Output:
  1091.  *      None
  1092.  */
  1093. #ifndef IGNORE_CONVERT
  1094. XtPointer CONVERT
  1095. ARGLIST((w, from_string, to_type, to_size, success))
  1096. ARG(Widget, w)
  1097. ARG(char *, from_string)
  1098. ARG(char *, to_type)
  1099. ARG(int, to_size)
  1100. GRA(Boolean *, success)
  1101. {
  1102.     XrmValue        fromVal, toVal;    /* resource holders        */
  1103.     Boolean        convResult;    /* return value            */
  1104.     unsigned char    oByte;        /* one byte result        */
  1105.     unsigned short    tByte;        /* two byte result        */
  1106.     XtPointer        fByte;        /* four byte result        */
  1107.     XtPointer        aByte;        /* allocated result        */
  1108.     
  1109.     /*
  1110.      * Zero it.
  1111.      */
  1112.     fByte = aByte = NULL;
  1113.     *success = False;
  1114.  
  1115.     /*
  1116.      * Sometimes we do not know this at code output.
  1117.      */
  1118.     if (to_size == 0)
  1119.     {
  1120.     if (!strcmp(to_type, XmRXmString) || !strcmp(to_type, XmRXmStringTable))
  1121.     {
  1122.         to_size = sizeof(XtPointer);
  1123.     }
  1124.     else
  1125.     {
  1126.         to_size = strlen(from_string);
  1127.     }
  1128.     }
  1129.         
  1130.     /*
  1131.      * Set up the list.
  1132.      */
  1133.     fromVal.size = strlen(from_string) + 1;
  1134.     fromVal.addr = from_string;
  1135.  
  1136.     switch( to_size )
  1137.     {
  1138.     case 1:
  1139.     toVal.size = sizeof(unsigned char);
  1140.     toVal.addr = (XTPOINTER)&oByte;
  1141.     break;
  1142.     case 2:
  1143.     toVal.size = sizeof(unsigned short);
  1144.     toVal.addr = (XTPOINTER)&tByte;
  1145.     break;
  1146.     default:
  1147.     toVal.size = sizeof(XTPOINTER);
  1148.     toVal.addr = (XTPOINTER)&fByte;
  1149.     break;
  1150.     }
  1151.     
  1152.     convResult = XtConvertAndStore(w, 
  1153.                    XmRString, 
  1154.                    &fromVal,
  1155.                    to_type,
  1156.                    &toVal);
  1157.     
  1158.     if( convResult )
  1159.     {
  1160.     switch( to_size )
  1161.     {
  1162.     case 1:
  1163.         fByte = (XTPOINTER)oByte;
  1164.         break;
  1165.     case 2:
  1166.         fByte = (XTPOINTER)tByte;
  1167.         break;
  1168.     default:
  1169.         break;
  1170.     }
  1171.     }
  1172.     
  1173.  
  1174.     /*
  1175.      * Conversion will fail if we need more than 4 bytes.
  1176.      * For strings it will fail always the first time.
  1177.      */
  1178.     if( !convResult && toVal.size != to_size )
  1179.     {
  1180.     /*
  1181.      * Need to allocate more space for this one.
  1182.      */
  1183.     toVal.addr = (XTPOINTER)XtMalloc(toVal.size);
  1184.     fByte = aByte = toVal.addr;
  1185.     convResult = XtConvertAndStore(w, 
  1186.                        XmRString, 
  1187.                        &fromVal,
  1188.                        to_type,
  1189.                        &toVal);
  1190.     }
  1191.     
  1192.     /*
  1193.      * Free any thing useless we may have allocated.
  1194.      */
  1195.     if( !convResult )
  1196.     {
  1197.     XtFree((char*)aByte);
  1198.     aByte = NULL;
  1199.     }
  1200.     
  1201.     /*
  1202.      * Return the result.
  1203.      */
  1204.     *success = convResult;
  1205.     return(fByte);
  1206. }
  1207. #endif
  1208.  
  1209. /*
  1210.  * Function:
  1211.  *      MENU_POST(p, mw, ev, dispatch);
  1212.  * Description:
  1213.  *      A converter wrapper for convenience from BuilderXcessory.
  1214.  * Input:
  1215.  *      p - Widget : the widget to post
  1216.  *    mw - XtPointer : the menu widget
  1217.  *    ev - XEvent* : the event that caused the menu post
  1218.  *    dispatch - Boolean* : not used
  1219.  * Output:
  1220.  *      None
  1221.  */
  1222.  
  1223. #ifndef IGNORE_MENU_POST
  1224.  
  1225. void MENU_POST
  1226. ARGLIST((p, mw, ev, dispatch))
  1227. ARG(Widget, p)
  1228. ARG(XtPointer, mw)
  1229. ARG(XEvent *, ev)
  1230. GRA(Boolean *, dispatch)
  1231. {
  1232.     Arg    args[2];
  1233.     int    argcnt;
  1234.     int    button;
  1235.     Widget m = (Widget)mw;
  1236.     XButtonEvent *e = (XButtonEvent *)ev;
  1237.  
  1238.     argcnt = 0;
  1239.     XtSetArg(args[argcnt], XmNwhichButton, &button);
  1240.     argcnt++;
  1241.     XtGetValues(m, args, argcnt);
  1242.     if( e->button != button) return;
  1243.     XmMenuPosition(m, e);
  1244.     XtManageChild(m);
  1245. }
  1246. #endif
  1247.  
  1248. /*
  1249.  * Function:
  1250.  *      SET_BACKGROUND_COLOR()
  1251.  * Description:
  1252.  *      Sets the background color and shadows of a widget.
  1253.  * Input:
  1254.  *      w - The widget to set the background color on.
  1255.  *      args, argcnt - The argument list so far.
  1256.  *      bg_color - The new background color as a pixel.
  1257.  * Output:
  1258.  *      none
  1259.  *
  1260.  *  NOTES:  This assumes that args later in the argument list
  1261.  *          override those already in the list.  Therfore i f
  1262.  *          there are shadow colors later in the list they will win.
  1263.  *        
  1264.  *          There is no need to use this function when creating a widget
  1265.  *          only when doing a set values, shadow colors are automatically
  1266.  *          calculated at creation time.
  1267.  */
  1268.  
  1269. void SET_BACKGROUND_COLOR
  1270. ARGLIST((w, args, argcnt, bg_color))
  1271. ARG(Widget, w)
  1272. ARG(ArgList, args)
  1273. ARG(Cardinal *, argcnt)
  1274. GRA(Pixel, bg_color)
  1275. {
  1276.     int i, topShadowLoc, bottomShadowLoc, selectLoc, fgLoc;
  1277.     Boolean argok = False;
  1278.  
  1279. #if (( XmVERSION == 1 ) && (XmREVISION > 0))
  1280.  
  1281.     /*
  1282.      * Walk through the arglist to see if the user set the top or
  1283.      * bottom shadow colors.
  1284.      */
  1285.  
  1286.     selectLoc = topShadowLoc =  bottomShadowLoc = UNSET;
  1287.     for (i = 0; i < *argcnt; i++)
  1288.     {
  1289.     if ((strcmp(args[i].name, XmNtopShadowColor) == 0) ||
  1290.         (strcmp(args[i].name, XmNtopShadowPixmap) == 0))
  1291.     {
  1292.         topShadowLoc = i;
  1293.     }
  1294.     else if ((strcmp(args[i].name, XmNbottomShadowColor) == 0) ||
  1295.          (strcmp(args[i].name, XmNbottomShadowPixmap) == 0))
  1296.     {
  1297.         bottomShadowLoc = i;
  1298.     }
  1299.     else if (strcmp(args[i].name, XmNarmColor) == 0)
  1300.     {
  1301.         selectLoc = i;
  1302.     }
  1303.     else if (strcmp(args[i].name, XmNforeground) == 0)
  1304.     {
  1305.         fgLoc = i;
  1306.     }
  1307.     }
  1308.  
  1309.     /*
  1310.      * If either the top or bottom shadow are not set then we
  1311.      * need to use XmGetColors to get the shadow colors from the backgound
  1312.      * color and add those that are not already in the arglist to the
  1313.      * arglist.
  1314.      * 
  1315.      */
  1316.  
  1317.     if (bottomShadowLoc == UNSET || topShadowLoc == UNSET ||
  1318.     selectLoc == UNSET || fgLoc == UNSET)
  1319.     {
  1320.     Arg larg[1];
  1321.     Colormap cmap;
  1322.     Pixel topShadow, bottomShadow, select, fgColor;
  1323.  
  1324.     XtSetArg(larg[0], XmNcolormap, &cmap);
  1325.     XtGetValues(w, larg, 1);
  1326.     XmGetColors(XtScreen(w), cmap, bg_color, 
  1327.             &fgColor, &topShadow, &bottomShadow, &select);
  1328.  
  1329.     if (topShadowLoc == UNSET)
  1330.     {
  1331.         XtSetArg(args[*argcnt], XmNtopShadowColor, topShadow); 
  1332.         (*argcnt)++;
  1333.     }
  1334.     
  1335.     if (bottomShadowLoc == UNSET)
  1336.     {
  1337.         XtSetArg(args[*argcnt], XmNbottomShadowColor, bottomShadow); 
  1338.         (*argcnt)++;
  1339.     }
  1340.  
  1341.     if (selectLoc == UNSET)
  1342.     {
  1343.         XtSetArg(args[*argcnt], XmNarmColor, select); 
  1344.         (*argcnt)++;
  1345.     }
  1346.  
  1347.     if (fgLoc == UNSET)
  1348.     {
  1349.         XtSetArg(args[*argcnt], XmNforeground, fgColor); 
  1350.         (*argcnt)++;
  1351.     }
  1352.     }
  1353. #endif
  1354.  
  1355.     XtSetArg(args[*argcnt], XmNbackground, bg_color); (*argcnt)++;
  1356. }
  1357. /****************************************************************************
  1358.  *
  1359.  * Big chunk of code inserted from Bull
  1360.  *
  1361.  ****************************************************************************/
  1362.  
  1363. #ifndef IGNORE_XPM_PIXMAP
  1364.  
  1365. /*
  1366.  * Copyright 1990, 1991 GROUPE BULL
  1367.  *
  1368.  * Permission to use, copy, modify, and distribute this software and its
  1369.  * documentation for any purpose and without fee is hereby granted, provided
  1370.  * that the above copyright notice appear in all copies and that both that
  1371.  * copyright notice and this permission notice appear in supporting
  1372.  * documentation, and that the name of GROUPE BULL not be used in advertising
  1373.  * or publicity pertaining to distribution of the software without specific,
  1374.  * written prior permission.  GROUPE BULL makes no representations about the
  1375.  * suitability of this software for any purpose.  It is provided "as is"
  1376.  * without express or implied warranty.
  1377.  *
  1378.  * GROUPE BULL disclaims all warranties with regard to this software,
  1379.  * including all implied warranties of merchantability and fitness,
  1380.  * in no event shall GROUPE BULL be liable for any special,
  1381.  * indirect or consequential damages or any damages
  1382.  * whatsoever resulting from loss of use, data or profits,
  1383.  * whether in an action of contract, negligence or other tortious
  1384.  * action, arising out of or in connection with the use 
  1385.  * or performance of this software.
  1386.  *
  1387.  */
  1388.  
  1389. /* Return ErrorStatus codes:
  1390.  * null     if full success
  1391.  * positive if partial success
  1392.  * negative if failure
  1393.  */
  1394.  
  1395. #define XpmColorError    1
  1396. #define XpmSuccess       0
  1397. #define XpmOpenFailed   -1
  1398. #define XpmFileInvalid  -2
  1399. #define XpmNoMemory     -3
  1400. #define XpmColorFailed  -4
  1401.  
  1402. typedef struct {
  1403.     char *name;                         /* Symbolic color name */
  1404.     char *value;                        /* Color value */
  1405.     Pixel pixel;                        /* Color pixel */
  1406. }     XpmColorSymbol;
  1407.  
  1408. typedef struct {
  1409.     unsigned long valuemask;            /* Specifies which attributes are
  1410.                                          * defined */
  1411.  
  1412.     Visual *visual;                     /* Specifies the visual to use */
  1413.     Colormap colormap;                  /* Specifies the colormap to use */
  1414.     unsigned int depth;                 /* Specifies the depth */
  1415.     unsigned int width;                 /* Returns the width of the created
  1416.                                          * pixmap */
  1417.     unsigned int height;                /* Returns the height of the created
  1418.                                          * pixmap */
  1419.     unsigned int x_hotspot;             /* Returns the x hotspot's
  1420.                                          * coordinate */
  1421.     unsigned int y_hotspot;             /* Returns the y hotspot's
  1422.                                          * coordinate */
  1423.     unsigned int cpp;                   /* Specifies the number of char per
  1424.                                          * pixel */
  1425.     Pixel *pixels;                      /* List of used color pixels */
  1426.     unsigned int npixels;               /* Number of pixels */
  1427.     XpmColorSymbol *colorsymbols;       /* Array of color symbols to
  1428.                                          * override */
  1429.     unsigned int numsymbols;            /* Number of symbols */
  1430.     char *rgb_fname;                    /* RGB text file name */
  1431.  
  1432.     /* Infos */
  1433.     unsigned int ncolors;               /* Number of colors */
  1434.     char ***colorTable;                 /* Color table pointer */
  1435.     char *hints_cmt;                    /* Comment of the hints section */
  1436.     char *colors_cmt;                   /* Comment of the colors section */
  1437.     char *pixels_cmt;                   /* Comment of the pixels section */
  1438.     unsigned int mask_pixel;            /* Transparent pixel's color table
  1439.                                          * index */
  1440. }      XpmAttributes;
  1441.  
  1442. /* Xpm attribute value masks bits */
  1443. #define XpmVisual          (1L<<0)
  1444. #define XpmColormap        (1L<<1)
  1445. #define XpmDepth           (1L<<2)
  1446. #define XpmSize            (1L<<3)      /* width & height */
  1447. #define XpmHotspot         (1L<<4)      /* x_hotspot & y_hotspot */
  1448. #define XpmCharsPerPixel   (1L<<5)
  1449. #define XpmColorSymbols    (1L<<6)
  1450. #define XpmRgbFilename     (1L<<7)
  1451. #define XpmInfos           (1L<<8)      /* all infos members */
  1452.  
  1453. #define XpmReturnPixels    (1L<<9)
  1454. #define XpmReturnInfos     XpmInfos
  1455.  
  1456. /*
  1457.  * minimal portability layer between ansi and KR C
  1458.  */
  1459.  
  1460. /* forward declaration of functions with prototypes */
  1461.  
  1462. #ifdef NeedFunctionPrototypes
  1463. #define FUNC(f, t, p) extern t f p
  1464. #define LFUNC(f, t, p) static t f p
  1465. #else
  1466. #define FUNC(f, t, p) extern t f()
  1467. #define LFUNC(f, t, p) static t f()
  1468. #endif
  1469.  
  1470. /*
  1471.  * functions declarations
  1472.  */
  1473.  
  1474. #ifdef __cplusplus
  1475. extern "C" {
  1476. #endif
  1477.  
  1478.     LFUNC(XpmCreatePixmapFromData, int, (Display * display,
  1479.                      Drawable d,
  1480.                      char **data,
  1481.                      Pixmap * pixmap_return,
  1482.                      Pixmap * shapemask_return,
  1483.                      XpmAttributes * attributes));
  1484.  
  1485.     LFUNC(XpmCreateImageFromData, int, (Display * display,
  1486.                                        char **data,
  1487.                                        XImage ** image_return,
  1488.                                        XImage ** shapemask_return,
  1489.                                        XpmAttributes * attributes));
  1490.  
  1491.     LFUNC(XpmFreeAttributes, void, (XpmAttributes * attributes));
  1492.  
  1493. #ifdef __cplusplus
  1494. }                                       /* for C++ V2.0 */
  1495. #endif
  1496.  
  1497.  
  1498. #ifdef SYSV
  1499. #define bcopy(source, dest, count) memcpy(dest, source, count)
  1500. #endif
  1501.  
  1502. typedef struct {
  1503.     unsigned int type;
  1504.     union {
  1505.         FILE *file;
  1506.         char **data;
  1507.     }     stream;
  1508.     char *cptr;
  1509.     unsigned int line;
  1510.     int CommentLength;
  1511.     char Comment[BUFSIZ];
  1512.     char *Bcmt, *Ecmt, Bos, Eos;
  1513.     unsigned int InsideString;          /* used during parsing: 0 or 1
  1514.                                          * whether we are inside or not */
  1515. }      xpmData;
  1516.  
  1517. #define XPMARRAY 0
  1518. #define XPMFILE  1
  1519. #define XPMPIPE  2
  1520.  
  1521. typedef unsigned char byte;
  1522.  
  1523. extern char *xpmColorKeys[];
  1524.  
  1525. #define TRANSPARENT_COLOR "None"        /* this must be a string! */
  1526.  
  1527. /* number of xpmColorKeys */
  1528. #define NKEYS 5
  1529.  
  1530. /*
  1531.  * key numbers for visual type, they must fit along with the number key of
  1532.  * each corresponding element in xpmColorKeys[] defined in xpm.h
  1533.  */
  1534. #define MONO    2
  1535. #define GRAY4   3
  1536. #define GRAY    4
  1537. #define COLOR   5
  1538.  
  1539. /* structure containing data related to an Xpm pixmap */
  1540. typedef struct {
  1541.     char *name;
  1542.     unsigned int width;
  1543.     unsigned int height;
  1544.     unsigned int cpp;
  1545.     unsigned int ncolors;
  1546.     char ***colorTable;
  1547.     unsigned int *pixelindex;
  1548.     XColor *xcolors;
  1549.     char **colorStrings;
  1550.     unsigned int mask_pixel;            /* mask pixel's colorTable index */
  1551. }      xpmInternAttrib;
  1552.  
  1553. #define UNDEF_PIXEL 0x80000000
  1554.  
  1555. char *xpmColorKeys[] =
  1556. {
  1557.  "s",                    /* key #1: symbol */
  1558.  "m",                    /* key #2: mono visual */
  1559.  "g4",                    /* key #3: 4 grays visual */
  1560.  "g",                    /* key #4: gray visual */
  1561.  "c",                    /* key #5: color visual */
  1562. };
  1563.  
  1564. /* XPM private routines */
  1565.  
  1566. LFUNC(xpmCreateImage, int, (Display * display,
  1567.                            xpmInternAttrib * attrib,
  1568.                            XImage ** image_return,
  1569.                            XImage ** shapeimage_return,
  1570.                            XpmAttributes * attributes));
  1571.  
  1572. LFUNC(xpmParseData, int, (xpmData * data,
  1573.                          xpmInternAttrib * attrib_return,
  1574.                          XpmAttributes * attributes));
  1575.  
  1576. LFUNC(xpmVisualType, int, (Visual * visual));
  1577. LFUNC(xpmFreeColorTable, void, (char ***colorTable, int ncolors));
  1578.  
  1579. LFUNC(xpmInitInternAttrib, void, (xpmInternAttrib * xmpdata));
  1580.  
  1581. LFUNC(xpmFreeInternAttrib, void, (xpmInternAttrib * xmpdata));
  1582.  
  1583. LFUNC(xpmSetAttributes, void, (xpmInternAttrib * attrib,
  1584.                              XpmAttributes * attributes));
  1585.  
  1586. /* I/O utility */
  1587.  
  1588. LFUNC(xpmNextString, void, (xpmData * mdata));
  1589. LFUNC(xpmNextUI, int, (xpmData * mdata, unsigned int *ui_return));
  1590. LFUNC(xpmGetC, int, (xpmData * mdata));
  1591. LFUNC(xpmUngetC, int, (int c, xpmData * mdata));
  1592. LFUNC(xpmNextWord, unsigned int, (xpmData * mdata, char *buf));
  1593. LFUNC(xpmGetCmt, void, (xpmData * mdata, char **cmt));
  1594. LFUNC(xpmOpenArray, int, (char **data, xpmData * mdata));
  1595. LFUNC(XpmDataClose, void, (xpmData * mdata));
  1596.  
  1597. /* RGB utility */
  1598.  
  1599. LFUNC(xpm_xynormalizeimagebits, void, (register unsigned char *bp,
  1600.                                      register XImage * img));
  1601. LFUNC(xpm_znormalizeimagebits, void, (register unsigned char *bp,
  1602.                                     register XImage * img));
  1603.  
  1604. /* Image utility */
  1605.  
  1606. LFUNC(SetColor, int, (Display * display, Colormap colormap, char *colorname,
  1607.               unsigned int color_index, Pixel * image_pixel,
  1608.               Pixel * mask_pixel, unsigned int *mask_pixel_index));
  1609.  
  1610. LFUNC(CreateXImage, int, (Display * display, Visual * visual,
  1611.               unsigned int depth, unsigned int width,
  1612.               unsigned int height, XImage ** image_return));
  1613.  
  1614. LFUNC(SetImagePixels, void, (XImage * image, unsigned int width,
  1615.                 unsigned int height, unsigned int *pixelindex,
  1616.                 Pixel * pixels));
  1617.  
  1618. LFUNC(SetImagePixels32, void, (XImage * image, unsigned int width,
  1619.                   unsigned int height, unsigned int *pixelindex,
  1620.                   Pixel * pixels));
  1621.  
  1622. LFUNC(SetImagePixels16, void, (XImage * image, unsigned int width,
  1623.                   unsigned int height, unsigned int *pixelindex,
  1624.                   Pixel * pixels));
  1625.  
  1626. LFUNC(SetImagePixels8, void, (XImage * image, unsigned int width,
  1627.                  unsigned int height, unsigned int *pixelindex,
  1628.                  Pixel * pixels));
  1629.  
  1630. LFUNC(SetImagePixels1, void, (XImage * image, unsigned int width,
  1631.                  unsigned int height, unsigned int *pixelindex,
  1632.                  Pixel * pixels));
  1633.  
  1634. LFUNC(atoui, unsigned int, (char *p, unsigned int l, unsigned int *ui_return));
  1635.  
  1636. /*
  1637.  * Macros
  1638.  *
  1639.  * The XYNORMALIZE macro determines whether XY format data requires
  1640.  * normalization and calls a routine to do so if needed. The logic in
  1641.  * this module is designed for LSBFirst byte and bit order, so
  1642.  * normalization is done as required to present the data in this order.
  1643.  *
  1644.  * The ZNORMALIZE macro performs byte and nibble order normalization if
  1645.  * required for Z format data.
  1646.  *
  1647.  * The XYINDEX macro computes the index to the starting byte (char) boundary
  1648.  * for a bitmap_unit containing a pixel with coordinates x and y for image
  1649.  * data in XY format.
  1650.  *
  1651.  * The ZINDEX* macros compute the index to the starting byte (char) boundary
  1652.  * for a pixel with coordinates x and y for image data in ZPixmap format.
  1653.  *
  1654.  */
  1655.  
  1656. #define XYNORMALIZE(bp, img) \
  1657.     if ((img->byte_order == MSBFirst) || (img->bitmap_bit_order == MSBFirst)) \
  1658.         xpm_xynormalizeimagebits((unsigned char *)(bp), img)
  1659.  
  1660. #define ZNORMALIZE(bp, img) \
  1661.     if (img->byte_order == MSBFirst) \
  1662.         xpm_znormalizeimagebits((unsigned char *)(bp), img)
  1663.  
  1664. #define XYINDEX(x, y, img) \
  1665.     ((y) * img->bytes_per_line) + \
  1666.     (((x) + img->xoffset) / img->bitmap_unit) * (img->bitmap_unit >> 3)
  1667.  
  1668. #define ZINDEX(x, y, img) ((y) * img->bytes_per_line) + \
  1669.     (((x) * img->bits_per_pixel) >> 3)
  1670.  
  1671. #define ZINDEX32(x, y, img) ((y) * img->bytes_per_line) + ((x) << 2)
  1672.  
  1673. #define ZINDEX16(x, y, img) ((y) * img->bytes_per_line) + ((x) << 1)
  1674.  
  1675. #define ZINDEX8(x, y, img) ((y) * img->bytes_per_line) + (x)
  1676.  
  1677. #define ZINDEX1(x, y, img) ((y) * img->bytes_per_line) + ((x) >> 3)
  1678.  
  1679. #if __STDC__
  1680. #define Const const
  1681. #else
  1682. #define Const
  1683. #endif
  1684.  
  1685. Pixmap XPM_PIXMAP
  1686. ARGLIST((w, pixmapName))
  1687. ARG(Widget, w)
  1688. GRA(char **, pixmapName)
  1689. {
  1690.     XpmAttributes    attributes;
  1691.     int            argcnt;
  1692.     Arg            args[10];
  1693.     Pixmap        pixmap;
  1694.     Pixmap        shape;
  1695.     int            returnValue;
  1696.     
  1697.     argcnt = 0;
  1698.     XtSetArg(args[argcnt], XmNdepth, &(attributes.depth)); argcnt++;
  1699.     XtSetArg(args[argcnt], XmNcolormap, &(attributes.colormap)); argcnt++;
  1700.     XtGetValues(w, args, argcnt);
  1701.  
  1702.     attributes.visual = DefaultVisual(XtDisplay(w),
  1703.                       DefaultScreen(XtDisplay(w)));
  1704.     attributes.valuemask = (XpmDepth | XpmColormap | XpmVisual);
  1705.     
  1706.     returnValue = XpmCreatePixmapFromData(XtDisplay(w),
  1707.                       DefaultRootWindow(XtDisplay(w)),
  1708.                       pixmapName, &pixmap, &shape,
  1709.                       &attributes);
  1710.     if ( shape )
  1711.     {
  1712.     XFreePixmap(XtDisplay(w), shape);
  1713.     }    
  1714.  
  1715.     switch(returnValue)
  1716.     {
  1717.     case XpmOpenFailed:
  1718.     case XpmFileInvalid:
  1719.     case XpmNoMemory:
  1720.     case XpmColorFailed:
  1721.     XtWarning("Could not create pixmap.");
  1722.     return(XmUNSPECIFIED_PIXMAP);
  1723.     default:
  1724.     return(pixmap);
  1725.     }
  1726. }
  1727.  
  1728. static unsigned int atoui
  1729. ARGLIST((p, l, ui_return))
  1730. ARG(register char *, p)
  1731. ARG(unsigned int, l)
  1732. GRA(unsigned int *, ui_return)
  1733. {
  1734.     register int n, i;
  1735.  
  1736.     n = 0;
  1737.     for (i = 0; i < l; i++)
  1738.         if (*p >= '0' && *p <= '9')
  1739.             n = n * 10 + *p++ - '0';
  1740.         else
  1741.             break;
  1742.  
  1743.     if (i != 0 && i == l) {
  1744.         *ui_return = n;
  1745.         return 1;
  1746.     } else
  1747.         return 0;
  1748. }
  1749.  
  1750. static int XpmCreatePixmapFromData
  1751. ARGLIST((display, d, data, pixmap_return, shapemask_return, attributes))
  1752. ARG(Display *, display)
  1753. ARG(Drawable, d)
  1754. ARG(char **, data)
  1755. ARG(Pixmap *, pixmap_return)
  1756. ARG(Pixmap *, shapemask_return)
  1757. GRA(XpmAttributes *,attributes)
  1758. {
  1759.     XImage *image, **imageptr = NULL;
  1760.     XImage *shapeimage, **shapeimageptr = NULL;
  1761.     int ErrorStatus;
  1762.     XGCValues gcv;
  1763.     GC gc;
  1764.  
  1765.     /*
  1766.      * initialize return values
  1767.      */
  1768.     if (pixmap_return) {
  1769.         *pixmap_return = NULL;
  1770.         imageptr = ℑ
  1771.     }
  1772.     if (shapemask_return) {
  1773.         *shapemask_return = NULL;
  1774.         shapeimageptr = &shapeimage;
  1775.     }
  1776.  
  1777.     /*
  1778.      * create the images
  1779.      */
  1780.     ErrorStatus = XpmCreateImageFromData(display, data, imageptr,
  1781.                                          shapeimageptr, attributes);
  1782.     if (ErrorStatus < 0)
  1783.         return (ErrorStatus);
  1784.  
  1785.     /*
  1786.      * create the pixmaps
  1787.      */
  1788.     if (imageptr && image) {
  1789.         *pixmap_return = XCreatePixmap(display, d, image->width,
  1790.                                        image->height, image->depth);
  1791.         gcv.function = GXcopy;
  1792.         gc = XCreateGC(display, *pixmap_return, GCFunction, &gcv);
  1793.  
  1794.         XPutImage(display, *pixmap_return, gc, image, 0, 0, 0, 0,
  1795.                   image->width, image->height);
  1796.  
  1797.         XDestroyImage(image);
  1798.         XFreeGC(display, gc);
  1799.     }
  1800.     if (shapeimageptr && shapeimage) {
  1801.         *shapemask_return = XCreatePixmap(display, d, shapeimage->width,
  1802.                                           shapeimage->height,
  1803.                                           shapeimage->depth);
  1804.         gcv.function = GXcopy;
  1805.         gc = XCreateGC(display, *shapemask_return, GCFunction, &gcv);
  1806.  
  1807.         XPutImage(display, *shapemask_return, gc, shapeimage, 0, 0, 0, 0,
  1808.                   shapeimage->width, shapeimage->height);
  1809.  
  1810.         XDestroyImage(shapeimage);
  1811.         XFreeGC(display, gc);
  1812.     }
  1813.     return (ErrorStatus);
  1814. }
  1815.  
  1816.  
  1817. static int XpmCreateImageFromData
  1818. ARGLIST((display, data, image_return, shapeimage_return, attributes))
  1819. ARG(Display *,display)
  1820. ARG(char **, data)
  1821. ARG(XImage **, image_return)
  1822. ARG(XImage **, shapeimage_return)
  1823. GRA(XpmAttributes *, attributes)
  1824. {
  1825.     xpmData mdata;
  1826.     int ErrorStatus;
  1827.     xpmInternAttrib attrib;
  1828.  
  1829.     /*
  1830.      * initialize return values
  1831.      */
  1832.     if (image_return)
  1833.         *image_return = NULL;
  1834.     if (shapeimage_return)
  1835.         *shapeimage_return = NULL;
  1836.  
  1837.     if ((ErrorStatus = xpmOpenArray(data, &mdata)) != XpmSuccess)
  1838.         return (ErrorStatus);
  1839.  
  1840.     xpmInitInternAttrib(&attrib);
  1841.  
  1842.     ErrorStatus = xpmParseData(&mdata, &attrib, attributes);
  1843.  
  1844.     if (ErrorStatus == XpmSuccess)
  1845.         ErrorStatus = xpmCreateImage(display, &attrib, image_return,
  1846.                                      shapeimage_return, attributes);
  1847.  
  1848.     if (ErrorStatus >= 0)
  1849.         xpmSetAttributes(&attrib, attributes);
  1850.     else if (attributes)
  1851.         XpmFreeAttributes(attributes);
  1852.  
  1853.     xpmFreeInternAttrib(&attrib);
  1854.     XpmDataClose(&mdata);
  1855.  
  1856.     return (ErrorStatus);
  1857. }
  1858.  
  1859. /*
  1860.  * open the given array to be read or written as an xpmData which is returned
  1861.  */
  1862. static int xpmOpenArray
  1863. ARGLIST((data, mdata))
  1864. ARG(char **,data)
  1865. GRA(xpmData *,mdata)
  1866. {
  1867.     mdata->type = XPMARRAY;
  1868.     mdata->stream.data = data;
  1869.     mdata->cptr = *data;
  1870.     mdata->line = 0;
  1871.     mdata->CommentLength = 0;
  1872.     mdata->Bcmt = mdata->Ecmt = NULL;
  1873.     mdata->Bos = mdata->Eos = '\0';
  1874.     mdata->InsideString = 0;
  1875.     return (XpmSuccess);
  1876. }
  1877.  
  1878. /*
  1879.  * Intialize the xpmInternAttrib pointers to Null to know
  1880.  * which ones must be freed later on.
  1881.  */
  1882. static void xpmInitInternAttrib
  1883. ARGLIST((attrib))
  1884. GRA(xpmInternAttrib *,attrib)
  1885. {
  1886.     attrib->ncolors = 0;
  1887.     attrib->colorTable = NULL;
  1888.     attrib->pixelindex = NULL;
  1889.     attrib->xcolors = NULL;
  1890.     attrib->colorStrings = NULL;
  1891.     attrib->mask_pixel = UNDEF_PIXEL;
  1892. }
  1893.  
  1894. /* function call in case of error, frees only localy allocated variables */
  1895. #undef RETURN
  1896. #define RETURN(status) \
  1897.   { if (colorTable) xpmFreeColorTable(colorTable, ncolors); \
  1898.     if (chars) free(chars); \
  1899.     if (pixelindex) free((char *)pixelindex); \
  1900.     if (hints_cmt)  free((char *)hints_cmt); \
  1901.     if (colors_cmt) free((char *)colors_cmt); \
  1902.     if (pixels_cmt) free((char *)pixels_cmt); \
  1903.     return(status); }
  1904.  
  1905. /*
  1906.  * This function parses an Xpm file or data and store the found informations
  1907.  * in an an xpmInternAttrib structure which is returned.
  1908.  */
  1909. static int xpmParseData
  1910. ARGLIST((data, attrib_return, attributes))
  1911. ARG(xpmData *,data)
  1912. ARG(xpmInternAttrib *, attrib_return)
  1913. GRA(XpmAttributes *, attributes)
  1914. {
  1915.     /* variables to return */
  1916.     unsigned int width, height;
  1917.     unsigned int ncolors = 0;
  1918.     unsigned int cpp;
  1919.     unsigned int x_hotspot, y_hotspot, hotspot = 0;
  1920.     char ***colorTable = NULL;
  1921.     unsigned int *pixelindex = NULL;
  1922.     char *hints_cmt = NULL;
  1923.     char *colors_cmt = NULL;
  1924.     char *pixels_cmt = NULL;
  1925.  
  1926.     /* calculation variables */
  1927.     unsigned int rncolors = 0;        /* read number of colors, it is
  1928.                      * different to ncolors to avoid
  1929.                      * problem when freeing the
  1930.                      * colorTable in case an error
  1931.                      * occurs while reading the hints
  1932.                      * line */
  1933.     unsigned int key;            /* color key */
  1934.     char *chars = NULL, buf[BUFSIZ];
  1935.     unsigned int *iptr;
  1936.     unsigned int a, b, x, y, l;
  1937.  
  1938.     unsigned int curkey;        /* current color key */
  1939.     unsigned int lastwaskey;        /* key read */
  1940.     char curbuf[BUFSIZ];        /* current buffer */
  1941.  
  1942.     /*
  1943.      * read hints: width, height, ncolors, chars_per_pixel 
  1944.      */
  1945.     if (!(xpmNextUI(data, &width) && xpmNextUI(data, &height)
  1946.       && xpmNextUI(data, &rncolors) && xpmNextUI(data, &cpp)))
  1947.     RETURN(XpmFileInvalid);
  1948.  
  1949.     ncolors = rncolors;
  1950.  
  1951.     /*
  1952.      * read hotspot coordinates if any 
  1953.      */
  1954.     hotspot = xpmNextUI(data, &x_hotspot) && xpmNextUI(data, &y_hotspot);
  1955.  
  1956.     /*
  1957.      * store the hints comment line 
  1958.      */
  1959.     if (attributes && (attributes->valuemask & XpmReturnInfos))
  1960.     xpmGetCmt(data, &hints_cmt);
  1961.  
  1962.     /*
  1963.      * read colors 
  1964.      */
  1965.     colorTable = (char ***) calloc(ncolors, sizeof(char **));
  1966.     if (!colorTable)
  1967.     RETURN(XpmNoMemory);
  1968.  
  1969.     for (a = 0; a < ncolors; a++) {
  1970.     xpmNextString(data);        /* skip the line */
  1971.     colorTable[a] = (char **) calloc((NKEYS + 1), sizeof(char *));
  1972.     if (!colorTable[a])
  1973.         RETURN(XpmNoMemory);
  1974.  
  1975.     /*
  1976.      * read pixel value 
  1977.      */
  1978.     colorTable[a][0] = (char *) malloc(cpp);
  1979.     if (!colorTable[a][0])
  1980.         RETURN(XpmNoMemory);
  1981.     for (b = 0; b < cpp; b++)
  1982.         colorTable[a][0][b] = xpmGetC(data);
  1983.  
  1984.     /*
  1985.      * read color keys and values 
  1986.      */
  1987.     curkey = 0;
  1988.     lastwaskey = 0;
  1989.     while (l = xpmNextWord(data, buf)) {
  1990.         if (!lastwaskey) {
  1991.         for (key = 1; key < NKEYS + 1; key++)
  1992.             if ((strlen(xpmColorKeys[key - 1]) == l)
  1993.             && (!strncmp(xpmColorKeys[key - 1], buf, l)))
  1994.             break;
  1995.         }
  1996.         if (!lastwaskey && key <= NKEYS) {    /* open new key */
  1997.         if (curkey) {        /* flush string */
  1998.             colorTable[a][curkey] =
  1999.             (char *) malloc(strlen(curbuf) + 1);
  2000.             if (!colorTable[a][curkey])
  2001.             RETURN(XpmNoMemory);
  2002.             strcpy(colorTable[a][curkey], curbuf);
  2003.         }
  2004.         curkey = key;        /* set new key  */
  2005.         curbuf[0] = '\0';    /* reset curbuf */
  2006.         lastwaskey = 1;
  2007.         } else {
  2008.         if (!curkey)
  2009.             RETURN(XpmFileInvalid);    /* key without value */
  2010.         if (!lastwaskey)
  2011.             strcat(curbuf, " ");/* append space */
  2012.         buf[l] = '\0';
  2013.         strcat(curbuf, buf);    /* append buf */
  2014.         lastwaskey = 0;
  2015.         }
  2016.     }
  2017.     if (!curkey)
  2018.         RETURN(XpmFileInvalid);    /* key without value */
  2019.     colorTable[a][curkey] = (char *) malloc(strlen(curbuf) + 1);
  2020.     if (!colorTable[a][curkey])
  2021.         RETURN(XpmNoMemory);
  2022.     strcpy(colorTable[a][curkey], curbuf);
  2023.     }
  2024.  
  2025.     /*
  2026.      * store the colors comment line 
  2027.      */
  2028.     if (attributes && (attributes->valuemask & XpmReturnInfos))
  2029.     xpmGetCmt(data, &colors_cmt);
  2030.  
  2031.     /*
  2032.      * read pixels and index them on color number 
  2033.      */
  2034.     pixelindex =
  2035.     (unsigned int *) malloc(sizeof(unsigned int) * width * height);
  2036.     if (!pixelindex)
  2037.     RETURN(XpmNoMemory);
  2038.  
  2039.     iptr = pixelindex;
  2040.  
  2041.     chars = (char *) malloc(cpp);
  2042.     if (!chars)
  2043.     RETURN(XpmNoMemory);
  2044.  
  2045.     for (y = 0; y < height; y++) {
  2046.     xpmNextString(data);
  2047.     for (x = 0; x < width; x++, iptr++) {
  2048.         for (a = 0; a < cpp; a++)
  2049.         chars[a] = xpmGetC(data);
  2050.         for (a = 0; a < ncolors; a++)
  2051.         if (!strncmp(colorTable[a][0], chars, cpp))
  2052.             break;
  2053.         if (a == ncolors)
  2054.         RETURN(XpmFileInvalid);    /* no color matches */
  2055.         *iptr = a;
  2056.     }
  2057.     }
  2058.  
  2059.     /*
  2060.      * store the pixels comment line 
  2061.      */
  2062.     if (attributes && (attributes->valuemask & XpmReturnInfos))
  2063.     xpmGetCmt(data, &pixels_cmt);
  2064.  
  2065.     free(chars);
  2066.  
  2067.     /*
  2068.      * store found informations in the xpmInternAttrib structure 
  2069.      */
  2070.     attrib_return->width = width;
  2071.     attrib_return->height = height;
  2072.     attrib_return->cpp = cpp;
  2073.     attrib_return->ncolors = ncolors;
  2074.     attrib_return->colorTable = colorTable;
  2075.     attrib_return->pixelindex = pixelindex;
  2076.  
  2077.     if (attributes) {
  2078.     if (attributes->valuemask & XpmReturnInfos) {
  2079.         attributes->hints_cmt = hints_cmt;
  2080.         attributes->colors_cmt = colors_cmt;
  2081.         attributes->pixels_cmt = pixels_cmt;
  2082.     }
  2083.     if (hotspot) {
  2084.         attributes->x_hotspot = x_hotspot;
  2085.         attributes->y_hotspot = y_hotspot;
  2086.         attributes->valuemask |= XpmHotspot;
  2087.     }
  2088.     }
  2089.     return (XpmSuccess);
  2090. }
  2091.  
  2092. /*
  2093.  * set the color pixel related to the given colorname,
  2094.  * return 0 if success, 1 otherwise.
  2095.  */
  2096.  
  2097. static int SetColor
  2098. ARGLIST((display, colormap,colorname, color_index, image_pixel, mask_pixel, mask_pixel_index))
  2099. ARG(Display *, display)
  2100. ARG(Colormap, colormap)
  2101. ARG(char *, colorname)
  2102. ARG(unsigned int, color_index)
  2103. ARG(Pixel *, image_pixel)
  2104. ARG(Pixel *, mask_pixel)
  2105. GRA(unsigned int *, mask_pixel_index)
  2106. {
  2107.     XColor xcolor;
  2108.  
  2109.     if (STRCASECMP(colorname, TRANSPARENT_COLOR)) {
  2110.     if (!XParseColor(display, colormap, colorname, &xcolor)
  2111.         || (!XAllocColor(display, colormap, &xcolor)))
  2112.         return (1);
  2113.     *image_pixel = xcolor.pixel;
  2114.     *mask_pixel = 1;
  2115.     } else {
  2116.     *image_pixel = 0;
  2117.     *mask_pixel = 0;
  2118.     *mask_pixel_index = color_index;/* store the color table index */
  2119.     }
  2120.     return (0);
  2121. }
  2122.  
  2123. /* function call in case of error, frees only localy allocated variables */
  2124. #undef RETURN
  2125. #define RETURN(status) \
  2126.   { if (image) XDestroyImage(image); \
  2127.     if (shapeimage) XDestroyImage(shapeimage); \
  2128.     if (image_pixels) free((char *)image_pixels); \
  2129.     if (mask_pixels) free((char *)mask_pixels); \
  2130.     return(status); }
  2131.  
  2132. static int xpmCreateImage
  2133. ARGLIST((display, attrib, image_return, shapeimage_return, attributes))
  2134. ARG(Display *, display)
  2135. ARG(xpmInternAttrib *, attrib)
  2136. ARG(XImage **, image_return)
  2137. ARG(XImage **, shapeimage_return)
  2138. GRA(XpmAttributes *, attributes)
  2139. {
  2140.     /* variables stored in the XpmAttributes structure */
  2141.     Visual *visual;
  2142.     Colormap colormap;
  2143.     unsigned int depth;
  2144.     XpmColorSymbol *colorsymbols;
  2145.     unsigned int numsymbols;
  2146.  
  2147.     /* variables to return */
  2148.     XImage *image = NULL;
  2149.     XImage *shapeimage = NULL;
  2150.     unsigned int mask_pixel;
  2151.     unsigned int ErrorStatus, ErrorStatus2;
  2152.  
  2153.     /* calculation variables */
  2154.     Pixel *image_pixels = NULL;
  2155.     Pixel *mask_pixels = NULL;
  2156.     char *colorname;
  2157.     unsigned int a, b, l;
  2158.     Boolean pixel_defined;
  2159.     unsigned int key;
  2160.  
  2161.  
  2162.     /*
  2163.      * retrieve information from the XpmAttributes 
  2164.      */
  2165.     if (attributes && attributes->valuemask & XpmColorSymbols) {
  2166.     colorsymbols = attributes->colorsymbols;
  2167.     numsymbols = attributes->numsymbols;
  2168.     } else
  2169.     numsymbols = 0;
  2170.  
  2171.     if (attributes && attributes->valuemask & XpmVisual)
  2172.     visual = attributes->visual;
  2173.     else
  2174.     visual = DefaultVisual(display, DefaultScreen(display));
  2175.  
  2176.     if (attributes && attributes->valuemask & XpmColormap)
  2177.     colormap = attributes->colormap;
  2178.     else
  2179.     colormap = DefaultColormap(display, DefaultScreen(display));
  2180.  
  2181.     if (attributes && attributes->valuemask & XpmDepth)
  2182.     depth = attributes->depth;
  2183.     else
  2184.     depth = DefaultDepth(display, DefaultScreen(display));
  2185.  
  2186.  
  2187.     ErrorStatus = XpmSuccess;
  2188.  
  2189.     /*
  2190.      * alloc pixels index tables 
  2191.      */
  2192.  
  2193.     key = xpmVisualType(visual);
  2194.     image_pixels = (Pixel *) malloc(sizeof(Pixel) * attrib->ncolors);
  2195.     if (!image_pixels)
  2196.     RETURN(XpmNoMemory);
  2197.  
  2198.     mask_pixels = (Pixel *) malloc(sizeof(Pixel) * attrib->ncolors);
  2199.     if (!mask_pixels)
  2200.     RETURN(XpmNoMemory);
  2201.  
  2202.     mask_pixel = UNDEF_PIXEL;
  2203.  
  2204.     /*
  2205.      * get pixel colors, store them in index tables 
  2206.      */
  2207.     for (a = 0; a < attrib->ncolors; a++) {
  2208.     colorname = NULL;
  2209.     pixel_defined = False;
  2210.  
  2211.     /*
  2212.      * look for a defined symbol 
  2213.      */
  2214.     if (numsymbols && attrib->colorTable[a][1]) {
  2215.         for (l = 0; l < numsymbols; l++)
  2216.         if (!strcmp(colorsymbols[l].name, attrib->colorTable[a][1]))
  2217.             break;
  2218.         if (l != numsymbols) {
  2219.         if (colorsymbols[l].value)
  2220.             colorname = colorsymbols[l].value;
  2221.         else
  2222.             pixel_defined = True;
  2223.         }
  2224.     }
  2225.     if (!pixel_defined) {        /* pixel not given as symbol value */
  2226.  
  2227.         if (colorname) {        /* colorname given as symbol value */
  2228.         if (!SetColor(display, colormap, colorname, a,
  2229.                &image_pixels[a], &mask_pixels[a], &mask_pixel))
  2230.             pixel_defined = True;
  2231.         else
  2232.             ErrorStatus = XpmColorError;
  2233.         }
  2234.         b = key;
  2235.         while (!pixel_defined && b > 1) {
  2236.         if (attrib->colorTable[a][b]) {
  2237.             if (!SetColor(display, colormap, attrib->colorTable[a][b],
  2238.                   a, &image_pixels[a], &mask_pixels[a],
  2239.                   &mask_pixel)) {
  2240.             pixel_defined = True;
  2241.             break;
  2242.             } else
  2243.             ErrorStatus = XpmColorError;
  2244.         }
  2245.         b--;
  2246.         }
  2247.  
  2248.         b = key + 1;
  2249.         while (!pixel_defined && b < NKEYS + 1) {
  2250.         if (attrib->colorTable[a][b]) {
  2251.             if (!SetColor(display, colormap, attrib->colorTable[a][b],
  2252.                   a, &image_pixels[a], &mask_pixels[a],
  2253.                   &mask_pixel)) {
  2254.             pixel_defined = True;
  2255.             break;
  2256.             } else
  2257.             ErrorStatus = XpmColorError;
  2258.         }
  2259.         b++;
  2260.         }
  2261.  
  2262.         if (!pixel_defined)
  2263.         RETURN(XpmColorFailed);
  2264.  
  2265.     } else {
  2266.         image_pixels[a] = colorsymbols[l].pixel;
  2267.         mask_pixels[a] = 1;
  2268.     }
  2269.     }
  2270.  
  2271.     /*
  2272.      * create the image 
  2273.      */
  2274.     if (image_return) {
  2275.     ErrorStatus2 = CreateXImage(display, visual, depth,
  2276.                     attrib->width, attrib->height, &image);
  2277.     if (ErrorStatus2 != XpmSuccess)
  2278.         RETURN(ErrorStatus2);
  2279.  
  2280.     /*
  2281.      * set the image data 
  2282.      *
  2283.      * In case depth is 1 or bits_per_pixel is 4, 6, 8, 24 or 32 use
  2284.      * optimized functions, otherwise use slower but sure general one. 
  2285.      *
  2286.      */
  2287.  
  2288.     if (image->depth == 1)
  2289.         SetImagePixels1(image, attrib->width, attrib->height,
  2290.                 attrib->pixelindex, image_pixels);
  2291.     else if (image->bits_per_pixel == 8)
  2292.         SetImagePixels8(image, attrib->width, attrib->height,
  2293.                 attrib->pixelindex, image_pixels);
  2294.     else if (image->bits_per_pixel == 16)
  2295.         SetImagePixels16(image, attrib->width, attrib->height,
  2296.                  attrib->pixelindex, image_pixels);
  2297.     else if (image->bits_per_pixel == 32)
  2298.         SetImagePixels32(image, attrib->width, attrib->height,
  2299.                  attrib->pixelindex, image_pixels);
  2300.     else
  2301.         SetImagePixels(image, attrib->width, attrib->height,
  2302.                attrib->pixelindex, image_pixels);
  2303.     }
  2304.  
  2305.     /*
  2306.      * create the shape mask image 
  2307.      */
  2308.     if (mask_pixel != UNDEF_PIXEL && shapeimage_return) {
  2309.     ErrorStatus2 = CreateXImage(display, visual, 1, attrib->width,
  2310.                     attrib->height, &shapeimage);
  2311.     if (ErrorStatus2 != XpmSuccess)
  2312.         RETURN(ErrorStatus2);
  2313.  
  2314.     SetImagePixels1(shapeimage, attrib->width, attrib->height,
  2315.             attrib->pixelindex, mask_pixels);
  2316.     }
  2317.     free((char *)mask_pixels);
  2318.  
  2319.     /*
  2320.      * if requested store allocated pixels in the XpmAttributes structure 
  2321.      */
  2322.     if (attributes &&
  2323.     (attributes->valuemask & XpmReturnInfos
  2324.      || attributes->valuemask & XpmReturnPixels)) {
  2325.     if (mask_pixel != UNDEF_PIXEL) {
  2326.         Pixel *pixels, *p1, *p2;
  2327.  
  2328.         attributes->npixels = attrib->ncolors - 1;
  2329.         pixels = (Pixel *) malloc(sizeof(Pixel) * attributes->npixels);
  2330.         if (pixels) {
  2331.         p1 = image_pixels;
  2332.         p2 = pixels;
  2333.         for (a = 0; a < attrib->ncolors; a++, p1++)
  2334.             if (a != mask_pixel)
  2335.             *p2++ = *p1;
  2336.         attributes->pixels = pixels;
  2337.         } else {
  2338.         /* if error just say we can't return requested data */
  2339.         attributes->valuemask &= ~XpmReturnPixels;
  2340.         attributes->valuemask &= ~XpmReturnInfos;
  2341.         attributes->pixels = NULL;
  2342.         attributes->npixels = 0;
  2343.         }
  2344.         free((char *)image_pixels);
  2345.     } else {
  2346.         attributes->pixels = image_pixels;
  2347.         attributes->npixels = attrib->ncolors;
  2348.     }
  2349.     attributes->mask_pixel = mask_pixel;
  2350.     } else
  2351.     free((char *)image_pixels);
  2352.  
  2353.  
  2354.     /*
  2355.      * return created images 
  2356.      */
  2357.     if (image_return)
  2358.     *image_return = image;
  2359.  
  2360.     if (shapeimage_return)
  2361.     *shapeimage_return = shapeimage;
  2362.  
  2363.     return (ErrorStatus);
  2364. }
  2365.  
  2366.  
  2367. /*
  2368.  * Create an XImage
  2369.  */
  2370. static int CreateXImage
  2371. ARGLIST((display, visual, depth, width, height, image_return))
  2372. ARG(Display *, display)
  2373. ARG(Visual *, visual)
  2374. ARG(unsigned int, depth)
  2375. ARG(unsigned int, width)
  2376. ARG(unsigned int, height)
  2377. GRA(XImage **, image_return)
  2378. {
  2379.     int bitmap_pad;
  2380.  
  2381.     /* first get bitmap_pad */
  2382.     if (depth > 16)
  2383.     bitmap_pad = 32;
  2384.     else if (depth > 8)
  2385.     bitmap_pad = 16;
  2386.     else
  2387.     bitmap_pad = 8;
  2388.  
  2389.     /* then create the XImage with data = NULL and bytes_per_line = 0 */
  2390.  
  2391.     *image_return = XCreateImage(display, visual, depth, ZPixmap, 0, 0,
  2392.                  width, height, bitmap_pad, 0);
  2393.     if (!*image_return)
  2394.     return (XpmNoMemory);
  2395.  
  2396.     /* now that bytes_per_line must have been set properly alloc data */
  2397.  
  2398.     (*image_return)->data =
  2399.     (char *) malloc((*image_return)->bytes_per_line * height);
  2400.  
  2401.     if (!(*image_return)->data) {
  2402.     XDestroyImage(*image_return);
  2403.     *image_return = NULL;
  2404.     return (XpmNoMemory);
  2405.     }
  2406.     return (XpmSuccess);
  2407. }
  2408.  
  2409.  
  2410. /*
  2411.  * The functions below are written from X11R5 MIT's code (XImUtil.c)
  2412.  *
  2413.  * The idea is to have faster functions than the standard XPutPixel function
  2414.  * to build the image data. Indeed we can speed up things by supressing tests
  2415.  * performed for each pixel. We do exactly the same tests but at the image
  2416.  * level. Assuming that we use only ZPixmap images. 
  2417.  */
  2418.  
  2419. LFUNC(_putbits, void, (register char *src, int dstoffset,
  2420.               register int numbits, register char *dst));
  2421.  
  2422. LFUNC(_XReverse_Bytes, void, (register unsigned char *bpt, register int nb));
  2423.  
  2424. static unsigned char Const _reverse_byte[0x100] = {
  2425.                 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
  2426.                 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
  2427.                 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
  2428.                 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
  2429.                 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
  2430.                 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
  2431.                 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
  2432.                 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
  2433.                 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
  2434.                 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
  2435.                 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
  2436.                 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
  2437.                 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
  2438.                 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
  2439.                 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
  2440.                 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
  2441.                 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
  2442.                 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
  2443.                 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
  2444.                 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
  2445.                 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
  2446.                 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
  2447.                 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
  2448.                 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
  2449.                 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
  2450.                 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
  2451.                 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
  2452.                 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
  2453.                 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
  2454.                 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
  2455.                 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
  2456.                  0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
  2457. };
  2458.  
  2459. static void _XReverse_Bytes
  2460. ARGLIST((bpt, nb))
  2461. ARG(register unsigned char *, bpt)
  2462. GRA(register int, nb)
  2463. {
  2464.     do {
  2465.     *bpt = _reverse_byte[*bpt];
  2466.     bpt++;
  2467.     } while (--nb > 0);
  2468. }
  2469.  
  2470. static void xpm_xynormalizeimagebits
  2471. ARGLIST((bp,img))
  2472. ARG(register unsigned char *, bp)
  2473. GRA(register XImage *, img)
  2474. {
  2475.     register unsigned char c;
  2476.  
  2477.     if (img->byte_order != img->bitmap_bit_order) {
  2478.     switch (img->bitmap_unit) {
  2479.  
  2480.     case 16:
  2481.         c = *bp;
  2482.         *bp = *(bp + 1);
  2483.         *(bp + 1) = c;
  2484.         break;
  2485.  
  2486.     case 32:
  2487.         c = *(bp + 3);
  2488.         *(bp + 3) = *bp;
  2489.         *bp = c;
  2490.         c = *(bp + 2);
  2491.         *(bp + 2) = *(bp + 1);
  2492.         *(bp + 1) = c;
  2493.         break;
  2494.     }
  2495.     }
  2496.     if (img->bitmap_bit_order == MSBFirst)
  2497.     _XReverse_Bytes(bp, img->bitmap_unit >> 3);
  2498. }
  2499.  
  2500. static void xpm_znormalizeimagebits
  2501. ARGLIST((bp,img))
  2502. ARG(register unsigned char *, bp)
  2503. GRA(register XImage *, img)
  2504. {
  2505.     register unsigned char c;
  2506.  
  2507.     switch (img->bits_per_pixel) {
  2508.  
  2509.     case 4:
  2510.     *bp = ((*bp >> 4) & 0xF) | ((*bp << 4) & ~0xF);
  2511.     break;
  2512.  
  2513.     case 16:
  2514.     c = *bp;
  2515.     *bp = *(bp + 1);
  2516.     *(bp + 1) = c;
  2517.     break;
  2518.  
  2519.     case 24:
  2520.     c = *(bp + 2);
  2521.     *(bp + 2) = *bp;
  2522.     *bp = c;
  2523.     break;
  2524.  
  2525.     case 32:
  2526.     c = *(bp + 3);
  2527.     *(bp + 3) = *bp;
  2528.     *bp = c;
  2529.     c = *(bp + 2);
  2530.     *(bp + 2) = *(bp + 1);
  2531.     *(bp + 1) = c;
  2532.     break;
  2533.     }
  2534. }
  2535.  
  2536. static unsigned char Const _lomask[0x09] = {
  2537.              0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
  2538. static unsigned char Const _himask[0x09] = {
  2539.              0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
  2540.  
  2541. static void _putbits
  2542. ARGLIST((src, dstoffset, numbits, dst))
  2543. ARG(register char *, src)        /* address of source bit string */
  2544. ARG(int, dstoffset)            /* bit offset into destination;
  2545.                      * range is 0-31 */
  2546. ARG(register int, numbits)        /* number of bits to copy to
  2547.                      * destination */
  2548. GRA(register char *, dst)        /* address of destination bit string */
  2549. {
  2550.     register unsigned char chlo, chhi;
  2551.     int hibits;
  2552.  
  2553.     dst = dst + (dstoffset >> 3);
  2554.     dstoffset = dstoffset & 7;
  2555.     hibits = 8 - dstoffset;
  2556.     chlo = *dst & _lomask[dstoffset];
  2557.     for (;;) {
  2558.     chhi = (*src << dstoffset) & _himask[dstoffset];
  2559.     if (numbits <= hibits) {
  2560.         chhi = chhi & _lomask[dstoffset + numbits];
  2561.         *dst = (*dst & _himask[dstoffset + numbits]) | chlo | chhi;
  2562.         break;
  2563.     }
  2564.     *dst = chhi | chlo;
  2565.     dst++;
  2566.     numbits = numbits - hibits;
  2567.     chlo = (unsigned char) (*src & _himask[hibits]) >> hibits;
  2568.     src++;
  2569.     if (numbits <= dstoffset) {
  2570.         chlo = chlo & _lomask[numbits];
  2571.         *dst = (*dst & _himask[numbits]) | chlo;
  2572.         break;
  2573.     }
  2574.     numbits = numbits - dstoffset;
  2575.     }
  2576. }
  2577.  
  2578. /*
  2579.  * Default method to write pixels into a Z image data structure.
  2580.  * The algorithm used is:
  2581.  *
  2582.  *    copy the destination bitmap_unit or Zpixel to temp
  2583.  *    normalize temp if needed
  2584.  *    copy the pixel bits into the temp
  2585.  *    renormalize temp if needed
  2586.  *    copy the temp back into the destination image data
  2587.  */
  2588.  
  2589. static void SetImagePixels
  2590. ARGLIST((image, width, height, pixelindex, pixels))
  2591. ARG(XImage *, image)
  2592. ARG(unsigned int, width)
  2593. ARG(unsigned int, height)
  2594. ARG(unsigned int *, pixelindex)
  2595. GRA(Pixel *, pixels)
  2596. {
  2597.     Pixel pixel;
  2598.     unsigned long px;
  2599.     register char *src;
  2600.     register char *dst;
  2601.     int nbytes;
  2602.     register unsigned int *iptr;
  2603.     register int x, y, i;
  2604.  
  2605.     iptr = pixelindex;
  2606.     if (image->depth == 1) {
  2607.     for (y = 0; y < height; y++)
  2608.         for (x = 0; x < width; x++, iptr++) {
  2609.         pixel = pixels[*iptr];
  2610.         for (i = 0, px = pixel;
  2611.              i < sizeof(unsigned long); i++, px >>= 8)
  2612.             ((unsigned char *) &pixel)[i] = (unsigned char)px;
  2613.         src = &image->data[XYINDEX(x, y, image)];
  2614.         dst = (char *) &px;
  2615.         px = 0;
  2616.         nbytes = image->bitmap_unit >> 3;
  2617.         for (i = nbytes; --i >= 0;)
  2618.             *dst++ = *src++;
  2619.         XYNORMALIZE(&px, image);
  2620.         i = ((x + image->xoffset) % image->bitmap_unit);
  2621.         _putbits((char *) &pixel, i, 1, (char *) &px);
  2622.         XYNORMALIZE(&px, image);
  2623.         src = (char *) &px;
  2624.         dst = &image->data[XYINDEX(x, y, image)];
  2625.         for (i = nbytes; --i >= 0;)
  2626.             *dst++ = *src++;
  2627.         }
  2628.     } else {
  2629.     for (y = 0; y < height; y++)
  2630.         for (x = 0; x < width; x++, iptr++) {
  2631.         pixel = pixels[*iptr];
  2632.         if (image->depth == 4)
  2633.             pixel &= 0xf;
  2634.         for (i = 0, px = pixel;
  2635.              i < sizeof(unsigned long); i++, px >>= 8)
  2636.             ((unsigned char *) &pixel)[i] = (unsigned char)px;
  2637.         src = &image->data[ZINDEX(x, y, image)];
  2638.         dst = (char *) &px;
  2639.         px = 0;
  2640.         nbytes = (image->bits_per_pixel + 7) >> 3;
  2641.         for (i = nbytes; --i >= 0;)
  2642.             *dst++ = *src++;
  2643.         ZNORMALIZE(&px, image);
  2644.         _putbits((char *) &pixel,
  2645.              (x * image->bits_per_pixel) & 7,
  2646.              image->bits_per_pixel, (char *) &px);
  2647.         ZNORMALIZE(&px, image);
  2648.         src = (char *) &px;
  2649.         dst = &image->data[ZINDEX(x, y, image)];
  2650.         for (i = nbytes; --i >= 0;)
  2651.             *dst++ = *src++;
  2652.         }
  2653.     }
  2654. }
  2655.  
  2656. /*
  2657.  * write pixels into a 32-bits Z image data structure
  2658.  */
  2659.  
  2660. #ifndef WORD64
  2661. static unsigned long byteorderpixel = MSBFirst << 24;
  2662.  
  2663. #endif
  2664.  
  2665. static void SetImagePixels32
  2666. ARGLIST((image, width, height, pixelindex, pixels))
  2667. ARG(XImage *, image)
  2668. ARG(unsigned int, width)
  2669. ARG(unsigned int, height)
  2670. ARG(unsigned int *, pixelindex)
  2671. GRA(Pixel *, pixels)
  2672. {
  2673.     register unsigned char *addr;
  2674.     register unsigned int *paddr;
  2675.     register unsigned int *iptr;
  2676.     register int x, y;
  2677.  
  2678.     iptr = pixelindex;
  2679. #ifndef WORD64
  2680.     if (*((char *) &byteorderpixel) == image->byte_order) {
  2681.     for (y = 0; y < height; y++)
  2682.         for (x = 0; x < width; x++, iptr++) {
  2683.         paddr =
  2684.             (unsigned int *)(&(image->data[ZINDEX32(x, y, image)]));
  2685.         *paddr = (unsigned int)pixels[*iptr];
  2686.         }
  2687.     } else
  2688. #endif
  2689.     if (image->byte_order == MSBFirst)
  2690.     for (y = 0; y < height; y++)
  2691.         for (x = 0; x < width; x++, iptr++) {
  2692.         addr = &((unsigned char *) image->data)[ZINDEX32(x, y, image)];
  2693.         addr[0] = (unsigned char)(pixels[*iptr] >> 24);
  2694.         addr[1] = (unsigned char)(pixels[*iptr] >> 16);
  2695.         addr[2] = (unsigned char)(pixels[*iptr] >> 8);
  2696.         addr[3] = (unsigned char)(pixels[*iptr]);
  2697.         }
  2698.     else
  2699.     for (y = 0; y < height; y++)
  2700.         for (x = 0; x < width; x++, iptr++) {
  2701.         addr = &((unsigned char *) image->data)[ZINDEX32(x, y, image)];
  2702.         addr[3] = (unsigned char)(pixels[*iptr] >> 24);
  2703.         addr[2] = (unsigned char)(pixels[*iptr] >> 16);
  2704.         addr[1] = (unsigned char)(pixels[*iptr] >> 8);
  2705.         addr[0] = (unsigned char)(pixels[*iptr]);
  2706.         }
  2707. }
  2708.  
  2709. /*
  2710.  * write pixels into a 16-bits Z image data structure
  2711.  */
  2712.  
  2713. static void SetImagePixels16
  2714. ARGLIST((image, width, height, pixelindex, pixels))
  2715. ARG(XImage *, image)
  2716. ARG(unsigned int, width)
  2717. ARG(unsigned int, height)
  2718. ARG(unsigned int *, pixelindex)
  2719. GRA(Pixel *, pixels)
  2720. {
  2721.     register unsigned char *addr;
  2722.     register unsigned int *iptr;
  2723.     register int x, y;
  2724.  
  2725.     iptr = pixelindex;
  2726.     if (image->byte_order == MSBFirst)
  2727.     for (y = 0; y < height; y++)
  2728.         for (x = 0; x < width; x++, iptr++) {
  2729.         addr = &((unsigned char *) image->data)[ZINDEX16(x, y, image)];
  2730.         addr[0] = (unsigned char)(pixels[*iptr] >> 8);
  2731.         addr[1] = (unsigned char)(pixels[*iptr]);
  2732.         }
  2733.     else
  2734.     for (y = 0; y < height; y++)
  2735.         for (x = 0; x < width; x++, iptr++) {
  2736.         addr = &((unsigned char *) image->data)[ZINDEX16(x, y, image)];
  2737.         addr[1] = (unsigned char)(pixels[*iptr] >> 8);
  2738.         addr[0] = (unsigned char)(pixels[*iptr]);
  2739.         }
  2740. }
  2741.  
  2742. /*
  2743.  * write pixels into a 8-bits Z image data structure
  2744.  */
  2745.  
  2746. static void SetImagePixels8
  2747. ARGLIST((image, width, height, pixelindex, pixels))
  2748. ARG(XImage *, image)
  2749. ARG(unsigned int, width)
  2750. ARG(unsigned int, height)
  2751. ARG(unsigned int *, pixelindex)
  2752. GRA(Pixel *, pixels)
  2753.  
  2754. {
  2755.     register unsigned int *iptr;
  2756.     register int x, y;
  2757.  
  2758.     iptr = pixelindex;
  2759.     for (y = 0; y < height; y++)
  2760.     for (x = 0; x < width; x++, iptr++)
  2761.         image->data[ZINDEX8(x, y, image)] = (char)pixels[*iptr];
  2762. }
  2763.  
  2764. /*
  2765.  * write pixels into a 1-bit depth image data structure and **offset null**
  2766.  */
  2767.  
  2768. static void SetImagePixels1
  2769. ARGLIST((image, width, height, pixelindex, pixels))
  2770. ARG(XImage *, image)
  2771. ARG(unsigned int, width)
  2772. ARG(unsigned int, height)
  2773. ARG(unsigned int *, pixelindex)
  2774. GRA(Pixel *, pixels)
  2775. {
  2776.     unsigned char bit;
  2777.     int xoff, yoff;
  2778.     register unsigned int *iptr;
  2779.     register int x, y;
  2780.  
  2781.     if (image->byte_order != image->bitmap_bit_order)
  2782.     SetImagePixels(image, width, height, pixelindex, pixels);
  2783.     else {
  2784.     iptr = pixelindex;
  2785.     if (image->bitmap_bit_order == MSBFirst)
  2786.         for (y = 0; y < height; y++)
  2787.         for (x = 0; x < width; x++, iptr++) {
  2788.             yoff = ZINDEX1(x, y, image);
  2789.             xoff = x & 7;
  2790.             bit = 0x80 >> xoff;
  2791.             if (pixels[*iptr] & 1)
  2792.             image->data[yoff] |= bit;
  2793.             else
  2794.             image->data[yoff] &= ~bit;
  2795.         }
  2796.     else
  2797.         for (y = 0; y < height; y++)
  2798.         for (x = 0; x < width; x++, iptr++) {
  2799.             yoff = ZINDEX1(x, y, image);
  2800.             xoff = x & 7;
  2801.             bit = 1 << xoff;
  2802.             if (pixels[*iptr] & 1)
  2803.             image->data[yoff] |= bit;
  2804.             else
  2805.             image->data[yoff] &= ~bit;
  2806.         }
  2807.     }
  2808. }
  2809.  
  2810. /*
  2811.  * Store into the XpmAttributes structure the required informations stored in
  2812.  * the xpmInternAttrib structure.
  2813.  */
  2814.  
  2815. static void xpmSetAttributes
  2816. ARGLIST((attrib, attributes))
  2817. ARG(xpmInternAttrib *, attrib)
  2818. GRA(XpmAttributes *, attributes)
  2819. {
  2820.     if (attributes) {
  2821.         if (attributes->valuemask & XpmReturnInfos) {
  2822.             attributes->cpp = attrib->cpp;
  2823.             attributes->ncolors = attrib->ncolors;
  2824.             attributes->colorTable = attrib->colorTable;
  2825.  
  2826.             attrib->ncolors = 0;
  2827.             attrib->colorTable = NULL;
  2828.         }
  2829.         attributes->width = attrib->width;
  2830.         attributes->height = attrib->height;
  2831.         attributes->valuemask |= XpmSize;
  2832.     }
  2833. }
  2834.  
  2835. /*
  2836.  * Free the XpmAttributes structure members
  2837.  * but the structure itself
  2838.  */
  2839.  
  2840. static void XpmFreeAttributes
  2841. ARGLIST((attributes))
  2842. GRA(XpmAttributes *, attributes)
  2843. {
  2844.     if (attributes) {
  2845.         if (attributes->valuemask & XpmReturnPixels && attributes->pixels) {
  2846.             free((char *)attributes->pixels);
  2847.             attributes->pixels = NULL;
  2848.             attributes->npixels = 0;
  2849.         }
  2850.         if (attributes->valuemask & XpmInfos) {
  2851.             if (attributes->colorTable) {
  2852.                 xpmFreeColorTable(attributes->colorTable, attributes->ncolors);
  2853.                 attributes->colorTable = NULL;
  2854.                 attributes->ncolors = 0;
  2855.             }
  2856.             if (attributes->hints_cmt) {
  2857.                 free(attributes->hints_cmt);
  2858.                 attributes->hints_cmt = NULL;
  2859.             }
  2860.             if (attributes->colors_cmt) {
  2861.                 free(attributes->colors_cmt);
  2862.                 attributes->colors_cmt = NULL;
  2863.             }
  2864.             if (attributes->pixels_cmt) {
  2865.                 free(attributes->pixels_cmt);
  2866.                 attributes->pixels_cmt = NULL;
  2867.             }
  2868.             if (attributes->pixels) {
  2869.                 free((char *)attributes->pixels);
  2870.                 attributes->pixels = NULL;
  2871.             }
  2872.         }
  2873.         attributes->valuemask = 0;
  2874.     }
  2875. }
  2876.  
  2877. /*
  2878.  * Free the xpmInternAttrib pointers which have been allocated
  2879.  */
  2880.  
  2881. static void xpmFreeInternAttrib
  2882. ARGLIST((attrib))
  2883. GRA(xpmInternAttrib *, attrib)
  2884. {
  2885.     unsigned int a;
  2886.  
  2887.     if (attrib->colorTable)
  2888.         xpmFreeColorTable(attrib->colorTable, attrib->ncolors);
  2889.     if (attrib->pixelindex)
  2890.         free((char *)attrib->pixelindex);
  2891.     if (attrib->xcolors)
  2892.         free((char *)attrib->xcolors);
  2893.     if (attrib->colorStrings) {
  2894.         for (a = 0; a < attrib->ncolors; a++)
  2895.             if (attrib->colorStrings[a])
  2896.                 free((char *)attrib->colorStrings[a]);
  2897.         free((char *)attrib->colorStrings);
  2898.     }
  2899. }
  2900.  
  2901. /*
  2902.  * close the file related to the xpmData if any
  2903.  */
  2904. static void XpmDataClose
  2905. ARGLIST((mdata))
  2906. GRA(xpmData *, mdata)
  2907. {
  2908.     switch (mdata->type) {
  2909.     case XPMARRAY:
  2910.         break;
  2911.     case XPMFILE:
  2912.         if (mdata->stream.file != (stdout) && mdata->stream.file != (stdin))
  2913.             fclose(mdata->stream.file);
  2914.         break;
  2915. #ifdef ZPIPE
  2916.     case XPMPIPE:
  2917.         pclose(mdata->stream.file);
  2918. #endif
  2919.     }
  2920. }
  2921.  
  2922. /*
  2923.  * skip whitespace and compute the following unsigned int,
  2924.  * returns 1 if one is found and 0 if not
  2925.  */
  2926. static int xpmNextUI
  2927. ARGLIST((mdata, ui_return))
  2928. ARG(xpmData *, mdata)
  2929. GRA(unsigned int *, ui_return)
  2930. {
  2931.     char buf[BUFSIZ];
  2932.     int l;
  2933.  
  2934.     l = xpmNextWord(mdata, buf);
  2935.     return atoui(buf, l, ui_return);
  2936. }
  2937.  
  2938. /*
  2939.  * get the current comment line
  2940.  */
  2941. static void xpmGetCmt
  2942. ARGLIST((mdata, cmt))
  2943. ARG(xpmData *, mdata)
  2944. GRA(char **, cmt)
  2945. {
  2946.     switch (mdata->type) {
  2947.     case XPMARRAY:
  2948.         *cmt = NULL;
  2949.         break;
  2950.     case XPMFILE:
  2951.     case XPMPIPE:
  2952.         if (mdata->CommentLength) {
  2953.             *cmt = (char *) malloc(mdata->CommentLength + 1);
  2954.             strncpy(*cmt, mdata->Comment, mdata->CommentLength);
  2955.             (*cmt)[mdata->CommentLength] = '\0';
  2956.             mdata->CommentLength = 0;
  2957.         } else
  2958.             *cmt = NULL;
  2959.         break;
  2960.     }
  2961. }
  2962.  
  2963. /*
  2964.  * skip to the end of the current string and the beginning of the next one
  2965.  */
  2966. static void xpmNextString
  2967. ARGLIST((mdata))
  2968. GRA(xpmData *, mdata)
  2969. {
  2970.     int c;
  2971.  
  2972.     switch (mdata->type) {
  2973.     case XPMARRAY:
  2974.         mdata->cptr = (mdata->stream.data)[++mdata->line];
  2975.         break;
  2976.     case XPMFILE:
  2977.     case XPMPIPE:
  2978.         if (mdata->Eos)
  2979.             while ((c = xpmGetC(mdata)) != mdata->Eos && c != EOF);
  2980.         if (mdata->Bos)                 /* if not natural XPM2 */
  2981.             while ((c = xpmGetC(mdata)) != mdata->Bos && c != EOF);
  2982.         break;
  2983.     }
  2984. }
  2985.  
  2986. /*
  2987.  * return the current character, skipping comments
  2988.  */
  2989. static int xpmGetC
  2990. ARGLIST((mdata))
  2991. GRA(xpmData *, mdata)
  2992. {
  2993.     int c;
  2994.     register unsigned int n = 0, a;
  2995.     unsigned int notend;
  2996.  
  2997.     switch (mdata->type) {
  2998.     case XPMARRAY:
  2999.         return (*mdata->cptr++);
  3000.     case XPMFILE:
  3001.     case XPMPIPE:
  3002.         c = getc(mdata->stream.file);
  3003.  
  3004.         if (mdata->Bos && mdata->Eos
  3005.             && (c == mdata->Bos || c == mdata->Eos)) {
  3006.             /* if not natural XPM2 */
  3007.             mdata->InsideString = !mdata->InsideString;
  3008.             return (c);
  3009.         }
  3010.         if (!mdata->InsideString && mdata->Bcmt && c == mdata->Bcmt[0]) {
  3011.             mdata->Comment[0] = c;
  3012.  
  3013.             /*
  3014.              * skip the string begining comment
  3015.              */
  3016.             do {
  3017.                 c = getc(mdata->stream.file);
  3018.                 mdata->Comment[++n] = c;
  3019.             } while (c == mdata->Bcmt[n] && mdata->Bcmt[n] != '\0'
  3020.                      && c != EOF);
  3021.  
  3022.             if (mdata->Bcmt[n] != '\0') {
  3023.                 /* this wasn't the begining of a comment */
  3024.                 /* put characters back in the order that we got them */
  3025.                 for (a = n; a > 0; a--)
  3026.                     xpmUngetC(mdata->Comment[a], mdata);
  3027.                 return (mdata->Comment[0]);
  3028.             }
  3029.  
  3030.             /*
  3031.              * store comment
  3032.              */
  3033.             mdata->Comment[0] = mdata->Comment[n];
  3034.             notend = 1;
  3035.             n = 0;
  3036.             while (notend) {
  3037.                 while (mdata->Comment[n] != mdata->Ecmt[0] && c != EOF) {
  3038.                     c = getc(mdata->stream.file);
  3039.                     mdata->Comment[++n] = c;
  3040.                 }
  3041.                 mdata->CommentLength = n;
  3042.                 a = 0;
  3043.                 do {
  3044.                     c = getc(mdata->stream.file);
  3045.                     n++;
  3046.                     a++;
  3047.                     mdata->Comment[n] = c;
  3048.                 } while (c == mdata->Ecmt[a] && mdata->Ecmt[a] != '\0'
  3049.                          && c != EOF);
  3050.                 if (mdata->Ecmt[a] == '\0') {
  3051.                     /* this is the end of the comment */
  3052.                     notend = 0;
  3053.                     xpmUngetC(mdata->Comment[n], mdata);
  3054.                 }
  3055.             }
  3056.             c = xpmGetC(mdata);
  3057.         }
  3058.         return (c);
  3059.     }
  3060. }
  3061.  
  3062.  
  3063. /*
  3064.  * push the given character back
  3065.  */
  3066. static int xpmUngetC
  3067. ARGLIST((c, mdata))
  3068. ARG(int, c)
  3069. GRA(xpmData *, mdata)
  3070. {
  3071.     switch (mdata->type) {
  3072.     case XPMARRAY:
  3073.         return (*--mdata->cptr = c);
  3074.     case XPMFILE:
  3075.     case XPMPIPE:
  3076.         if (mdata->Bos && (c == mdata->Bos || c == mdata->Eos))
  3077.             /* if not natural XPM2 */
  3078.             mdata->InsideString = !mdata->InsideString;
  3079.         return (ungetc(c, mdata->stream.file));
  3080.     }
  3081. }
  3082.  
  3083. /*
  3084.  * skip whitespace and return the following word
  3085.  */
  3086. static unsigned int xpmNextWord
  3087. ARGLIST((mdata, buf))
  3088. ARG(xpmData *, mdata)
  3089. GRA(char *, buf)
  3090. {
  3091.     register unsigned int n = 0;
  3092.     int c;
  3093.  
  3094.     switch (mdata->type) {
  3095.     case XPMARRAY:
  3096.         while (isspace(c = *mdata->cptr) && c != mdata->Eos)
  3097.             mdata->cptr++;
  3098.         do {
  3099.             c = *mdata->cptr++;
  3100.             buf[n++] = c;
  3101.         } while (!isspace(c) && c != mdata->Eos && c != '\0');
  3102.         n--;
  3103.         mdata->cptr--;
  3104.         break;
  3105.     case XPMFILE:
  3106.     case XPMPIPE:
  3107.         while (isspace(c = xpmGetC(mdata)) && c != mdata->Eos);
  3108.         while (!isspace(c) && c != mdata->Eos && c != EOF) {
  3109.             buf[n++] = c;
  3110.             c = xpmGetC(mdata);
  3111.         }
  3112.         xpmUngetC(c, mdata);
  3113.         break;
  3114.     }
  3115.     return (n);
  3116. }
  3117.  
  3118. static int xpmVisualType
  3119. ARGLIST((visual))
  3120. GRA(Visual *, visual)
  3121. {
  3122. #if defined(__cplusplus) || defined(c_plusplus)
  3123.     switch ( visual->c_class )
  3124. #else
  3125.     switch ( visual->class )
  3126. #endif
  3127.     {
  3128.     case StaticGray:
  3129.     case GrayScale:
  3130.     switch (visual->map_entries)
  3131.     {
  3132.     case 2:
  3133.         return (MONO);
  3134.     case 4:
  3135.         return (GRAY4);
  3136.     default:
  3137.         return (GRAY);
  3138.     }
  3139.     default:
  3140.     return (COLOR);
  3141.     }
  3142. }
  3143.  
  3144. /*
  3145.  * Free the computed color table
  3146.  */
  3147.  
  3148. static void xpmFreeColorTable
  3149. ARGLIST((colorTable, ncolors))
  3150. ARG(char ***, colorTable)
  3151. GRA(int, ncolors)
  3152. {
  3153.     int a, b;
  3154.  
  3155.     if (colorTable) {
  3156.         for (a = 0; a < ncolors; a++)
  3157.             if (colorTable[a]) {
  3158.                 for (b = 0; b < (NKEYS + 1); b++)
  3159.                     if (colorTable[a][b])
  3160.                         free(colorTable[a][b]);
  3161.                 free((char *)colorTable[a]);
  3162.             }
  3163.         free((char *)colorTable);
  3164.     }
  3165. }
  3166. #endif
  3167.